Compare commits

...

49 Commits

Author SHA1 Message Date
longpanda
b9b6852631 1.0.63 release 2021-12-20 20:20:07 +08:00
crim50n
4a44a82840 Adding support for MiniOS. (#1317)
* Create minios-hook.sh

* Create minios-disk.sh

* Update ventoy-hook.sh

* Update grub.cfg

* Update README.md
2021-12-20 16:20:31 +08:00
kheyyam
f2e82862ab Add Azerbaijani language (#1325) 2021-12-20 16:17:56 +08:00
gbrea
368151aa3b Added Galician Language (#1323)
* Update languages.json, added Galician language

* Added Galician Language
2021-12-20 16:17:31 +08:00
Hoàng Điềm Tĩnh
b5dcaecffe Update languages.json (#1320)
Please update Vietnamese Language.
2021-12-20 16:17:07 +08:00
longpanda
a4cfbd6799 Merge branch 'master' of https://github.com/ventoy/Ventoy 2021-12-08 11:55:23 +08:00
longpanda
ab964932cb Solus UEFI boot 2021-12-08 11:55:06 +08:00
VlatkoS
bcc81d31db Updated Macedonian language (#1309)
Updated Macedonian language
2021-12-06 09:48:58 +08:00
longpanda
91330b97bf Update grub.cfg 2021-12-05 21:02:14 +08:00
longpanda
fe7b9abcff Add missing manifest file. 2021-12-05 12:02:46 +08:00
longpanda
68d3b55167 misc update 2021-12-04 14:40:04 +08:00
longpanda
e1c26567a1 1. Add check for invalid characters in menu_class plugin.
2. Optimization for help language list process
2021-12-03 18:31:09 +08:00
4131d95cef add ja_JP translation for Grub help text (#1294) 2021-12-03 17:09:30 +08:00
longpanda
8c18f91ac1 Fix the "plugson.tar.xz not found" error, when the path contains unicode characters. 2021-12-03 14:21:47 +08:00
longpanda
73fabd0c65 1.0.62 release 2021-12-02 20:02:42 +08:00
longpanda
0c140cf378 support LibreELEC 10.0.1 (#1268) 2021-12-02 15:17:52 +08:00
longpanda
293f677cbf VentoyPlugson update 2021-12-02 10:55:37 +08:00
longpanda
4bf43ab9d4 VentoyPlugson ---- A GUI ventoy.json configurator 2021-12-01 20:43:35 +08:00
salevdns
9eeb94e8b5 Add encryption support to CreatePersistentImg.sh (#1130)
Added option to create persistent fs inside LUKS container.
Had to change to #!/bin/bash to parse interactive user input for the encryption passphrase.
The _freeloop=$freeloop part is kind of bad style, but I kept it for now to keep changes minimal.
2021-11-25 11:44:31 +08:00
Hildo Guillardi Júnior
f4987fd7f4 Update Brazilian Portoguese language (#1273) 2021-11-25 11:39:13 +08:00
Alexander Berger
157c6f13ec Updated Ukrainian and Russian localizations (#1269)
* Updated Ukrainian and Russian localizations

* comma in ukr locale
2021-11-25 11:38:55 +08:00
longpanda
6a506ee7f3 Optimization for FreeBSD fragments process. 2021-11-24 15:46:21 +08:00
longpanda
32643ecdbb compress 7za.exe 2021-11-23 17:29:25 +08:00
Ida Bagus
d2e5930520 Update languages.json (#1264) 2021-11-22 09:41:40 +08:00
944f376ffe Modify Japanese Localization (#1261)
- Corrected no-need spaces (e.g. spaces after punctuation).
- Unified the message style.
- Newly translated untranslated strings.
2021-11-20 13:51:20 +08:00
longpanda
d402338ade Optimization for shell script (#1259) 2021-11-19 09:15:09 +08:00
longpanda
d938100eeb 1. Add default_file option in theme plugin
2. Add F5 Tools --> Theme Select menu to swith between themes
2021-11-16 19:32:23 +08:00
longpanda
a4200ed99e Merge branch 'master' of https://github.com/ventoy/Ventoy 2021-11-16 15:05:05 +08:00
longpanda
e4ccd5115e Optimization for FreeBSD 2021-11-16 15:04:41 +08:00
marcellogianola
cdb727dd22 Update languages.json (#1247) 2021-11-16 08:57:40 +08:00
Thomas De Rocker
6b4093fb93 Update Dutch translations (#1246) 2021-11-15 23:21:51 +08:00
longpanda
21450d4a56 Update Ventoy2Disk.sh
(#1245)
2021-11-15 23:20:33 +08:00
longpanda
164c8d6505 Optimization for FreeBSD distro. 2021-11-15 16:00:30 +08:00
孟武.尼德霍格.龍
37e7a539f9 Update Traditional Chinese (#1240)
Update Traditional Chinese strings
2021-11-15 09:18:02 +08:00
longpanda
b5a649f96f 1.0.61 release 2021-11-13 22:49:51 +08:00
B.O.S.S
443a1344f2 Update Polish translation (#1233) 2021-11-13 19:55:48 +08:00
VenusGirl
d3de1a91f8 Update languages.json (#1227)
Korean Update
2021-11-13 19:55:35 +08:00
longpanda
580ad598f6 Merge branch 'master' of https://github.com/ventoy/Ventoy 2021-11-13 19:53:09 +08:00
longpanda
0891e34d47 1. Fix some bugs when do update after non-destructive installation.
2. Call chkdsk to fix the volume before shrink.
2021-11-13 19:52:42 +08:00
longpanda
4d777090cb Update README.md 2021-11-12 20:59:40 +08:00
longpanda
b0568922d2 1.0.60 release 2021-11-12 19:56:05 +08:00
soares23
69b6bb8fca Create de_DE.txt (#1223)
Create  Grub Help de_De.txt
2021-11-12 14:24:14 +08:00
bovirus
3d686c27d7 Update Italian translation (#1218)
@ventoy 

Please check and merge. Thanks.
2021-11-11 15:36:24 +08:00
Steve
90ba217ec7 updated german translation (#1216)
translated the new strings
2021-11-11 15:35:56 +08:00
Tayfun Akkoyun
fab070ef64 Update Turkish Language (#1215) 2021-11-11 15:35:26 +08:00
longpanda
b3869b6894 1.0.59 release 2021-11-10 19:44:40 +08:00
longpanda
563214ed40 Add experimental support for Non-destructive Installation in Windows. 2021-11-10 17:53:21 +08:00
longpanda
b67f738b00 Update for Ventoy2Disk.exe 2021-11-08 14:56:35 +08:00
longpanda
a9c539572b Show a warning message if ventoy.json is in UCS-2 encoding. (#1125)
ventoy.json must in UTF-8 encoding. The BOM is auto skipped if exist.
2021-11-08 14:55:08 +08:00
392 changed files with 84656 additions and 572 deletions

View File

@@ -21,7 +21,7 @@ body:
attributes:
label: Ventoy Version
description: What version of ventoy are you running?
placeholder: 1.0.58
placeholder: 1.0.63
validations:
required: true
- type: dropdown

View File

@@ -402,15 +402,24 @@ int g_menu_update_mode = 0;
int g_ventoy_tip_label_enable = 0;
const char * g_ventoy_tip_msg1 = NULL;
const char * g_ventoy_tip_msg2 = NULL;
char g_ventoy_theme_path[256] = {0};
static const char *g_ventoy_cur_img_path = NULL;
static void menu_set_chosen_tip(grub_menu_t menu, int entry)
{
int i;
img_info *img;
menu_tip *tip;
grub_menu_entry_t e = grub_menu_get_entry (menu, entry);
if (g_ventoy_theme_path[0])
{
grub_env_set("theme", g_ventoy_theme_path);
}
g_ventoy_tip_msg1 = g_ventoy_tip_msg2 = NULL;
if (e && e->id && grub_strncmp(e->id, "VID_", 4) == 0)
{
g_ventoy_theme_path[0] = 0;
img = (img_info *)(void *)grub_strtoul(e->id + 4, NULL, 16);
if (img)
{
@@ -419,6 +428,27 @@ static void menu_set_chosen_tip(grub_menu_t menu, int entry)
g_ventoy_cur_img_path = img->path;
}
}
else if (e && e->id && grub_strncmp(e->id, "DIR_", 4) == 0)
{
g_ventoy_theme_path[0] = 0;
for (i = 0; i < e->argc; i++)
{
if (e->args[i] && grub_strncmp(e->args[i], "_VTIP_", 6) == 0)
{
break;
}
}
if (i < e->argc)
{
tip = (menu_tip *)(void *)grub_strtoul(e->args[i] + 6, NULL, 16);
if (tip)
{
g_ventoy_tip_msg1 = tip->tip1;
g_ventoy_tip_msg2 = tip->tip2;
}
}
}
}
static void

View File

@@ -51,35 +51,11 @@
GRUB_MOD_LICENSE ("GPLv3+");
static grub_uint8_t g_check_mbr_data[440] = {
static grub_uint8_t g_check_mbr_data[] = {
0xEB, 0x63, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFA, 0x90, 0x90, 0xF6, 0xC2, 0x80, 0x74, 0x05, 0xF6, 0xC2, 0x70,
0x74, 0x02, 0xB2, 0x80, 0xEA, 0x79, 0x7C, 0x00, 0x00, 0x31, 0xC0, 0x8E, 0xD8, 0x8E, 0xD0, 0xBC,
0x00, 0x20, 0xFB, 0xA0, 0x64, 0x7C, 0x3C, 0xFF, 0x74, 0x02, 0x88, 0xC2, 0x52, 0xBE, 0x90, 0x7D,
0xE8, 0x16, 0x01, 0xBE, 0x05, 0x7C, 0xB4, 0x41, 0xBB, 0xAA, 0x55, 0xCD, 0x13, 0x5A, 0x52, 0x72,
0x3D, 0x81, 0xFB, 0x55, 0xAA, 0x75, 0x37, 0x83, 0xE1, 0x01, 0x74, 0x32, 0x31, 0xC0, 0x89, 0x44,
0x04, 0x40, 0x88, 0x44, 0xFF, 0x89, 0x44, 0x02, 0xC7, 0x04, 0x10, 0x00, 0x66, 0x8B, 0x1E, 0x5C,
0x7C, 0x66, 0x89, 0x5C, 0x08, 0x66, 0x8B, 0x1E, 0x60, 0x7C, 0x66, 0x89, 0x5C, 0x0C, 0xC7, 0x44,
0x06, 0x00, 0x70, 0xB4, 0x42, 0xCD, 0x13, 0x72, 0x05, 0xBB, 0x00, 0x70, 0xEB, 0x76, 0xB4, 0x08,
0xCD, 0x13, 0x73, 0x0D, 0x5A, 0x84, 0xD2, 0x0F, 0x83, 0xD8, 0x00, 0xBE, 0x96, 0x7D, 0xE9, 0x82,
0x00, 0x66, 0x0F, 0xB6, 0xC6, 0x88, 0x64, 0xFF, 0x40, 0x66, 0x89, 0x44, 0x04, 0x0F, 0xB6, 0xD1,
0xC1, 0xE2, 0x02, 0x88, 0xE8, 0x88, 0xF4, 0x40, 0x89, 0x44, 0x08, 0x0F, 0xB6, 0xC2, 0xC0, 0xE8,
0x02, 0x66, 0x89, 0x04, 0x66, 0xA1, 0x60, 0x7C, 0x66, 0x09, 0xC0, 0x75, 0x4E, 0x66, 0xA1, 0x5C,
0x7C, 0x66, 0x31, 0xD2, 0x66, 0xF7, 0x34, 0x88, 0xD1, 0x31, 0xD2, 0x66, 0xF7, 0x74, 0x04, 0x3B,
0x44, 0x08, 0x7D, 0x37, 0xFE, 0xC1, 0x88, 0xC5, 0x30, 0xC0, 0xC1, 0xE8, 0x02, 0x08, 0xC1, 0x88,
0xD0, 0x5A, 0x88, 0xC6, 0xBB, 0x00, 0x70, 0x8E, 0xC3, 0x31, 0xDB, 0xB8, 0x01, 0x02, 0xCD, 0x13,
0x72, 0x1E, 0x8C, 0xC3, 0x60, 0x1E, 0xB9, 0x00, 0x01, 0x8E, 0xDB, 0x31, 0xF6, 0xBF, 0x00, 0x80,
0x8E, 0xC6, 0xFC, 0xF3, 0xA5, 0x1F, 0x61, 0xFF, 0x26, 0x5A, 0x7C, 0xBE, 0x93, 0x7D, 0xEB, 0x03,
0xBE, 0x99, 0x7D, 0xE8, 0x33, 0x00, 0xBE, 0x9C, 0x7D, 0xE8, 0x2D, 0x00, 0xCD, 0x18, 0xEB, 0xFE,
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44, 0x00, 0x52, 0x64, 0x00, 0x20, 0x45, 0x72, 0x0D,
0x0A, 0x00, 0xBB, 0x01, 0x00, 0xB4, 0x0E, 0xCD, 0x10, 0xAC, 0x3C, 0x00, 0x75, 0xF4, 0xC3, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
initrd_info *g_initrd_img_list = NULL;
@@ -655,12 +631,8 @@ static int ventoy_check_official_device(grub_device_t dev)
grub_memset(mbr, 0, 512);
grub_disk_read(disk, 0, 0, 512, mbr);
grub_disk_close(disk);
g_check_mbr_data[92] = mbr[92];
g_check_mbr_data[102] = mbr[102];
g_check_mbr_data[103] = mbr[103];
grub_memcpy(g_check_mbr_data + 0x180, mbr + 0x180, 16);
if (grub_memcmp(g_check_mbr_data, mbr, 440))
if (grub_memcmp(g_check_mbr_data, mbr, 0x30) || grub_memcmp(g_check_mbr_data + 0x30, mbr + 0x190, 16))
{
return ventoy_set_check_result(12);
}
@@ -1866,7 +1838,7 @@ static int ventoy_collect_img_files(const char *filename, const struct grub_dirh
img->alias = ventoy_plugin_get_menu_alias(vtoy_alias_image_file, img->path);
tip = ventoy_plugin_get_menu_tip(img->path);
tip = ventoy_plugin_get_menu_tip(vtoy_tip_image_file, img->path);
if (tip)
{
img->tip1 = tip->tip1;
@@ -2067,7 +2039,8 @@ static int ventoy_dynamic_tree_menu(img_iterator_node *node)
const char *dir_class = NULL;
const char *dir_alias = NULL;
img_iterator_node *child = NULL;
const menu_tip *tip = NULL;
if (node->isocnt == 0 || node->done == 1)
{
return 0;
@@ -2107,20 +2080,22 @@ static int ventoy_dynamic_tree_menu(img_iterator_node *node)
dir_class = "vtoydir";
}
tip = ventoy_plugin_get_menu_tip(vtoy_tip_directory, node->dir);
dir_alias = ventoy_plugin_get_menu_alias(vtoy_alias_directory, node->dir);
if (dir_alias)
{
if (g_tree_view_menu_style == 0)
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
"DIR", dir_alias, dir_class, node->dir + offset);
"submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
"DIR", dir_alias, dir_class, node->dir + offset, tip);
}
else
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
dir_alias, dir_class, node->dir + offset);
"submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
dir_alias, dir_class, node->dir + offset, tip);
}
}
else
@@ -2130,14 +2105,14 @@ static int ventoy_dynamic_tree_menu(img_iterator_node *node)
if (g_tree_view_menu_style == 0)
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
"DIR", dir_alias, dir_class, node->dir + offset);
"submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
"DIR", dir_alias, dir_class, node->dir + offset, tip);
}
else
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
dir_alias, dir_class, node->dir + offset);
"submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
dir_alias, dir_class, node->dir + offset, tip);
}
}
@@ -5250,6 +5225,7 @@ static cmd_para ventoy_cmds[] =
{ "vt_unix_reset", ventoy_cmd_unix_reset, 0, NULL, "", "", NULL },
{ "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf, 0, NULL, "", "", NULL },
{ "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko, 0, NULL, "", "", NULL },
{ "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap, 0, NULL, "", "", NULL },
{ "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc, 0, NULL, "", "", NULL },
{ "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko, 0, NULL, "", "", NULL },
{ "vt_unix_chain_data", ventoy_cmd_unix_chain_data, 0, NULL, "", "", NULL },
@@ -5264,6 +5240,8 @@ static cmd_para ventoy_cmds[] =
{ "vt_sel_wimboot", ventoy_cmd_sel_wimboot, 0, NULL, "", "", NULL },
{ "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt, 0, NULL, "", "", NULL },
{ "vt_set_theme", ventoy_cmd_set_theme, 0, NULL, "", "", NULL },
{ "vt_set_theme_path", ventoy_cmd_set_theme_path, 0, NULL, "", "", NULL },
{ "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg, 0, NULL, "", "", NULL },
{ "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset, 0, NULL, "", "", NULL },
{ "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd, 0, NULL, "", "", NULL },

View File

@@ -896,8 +896,11 @@ typedef struct menu_alias
struct menu_alias *next;
}menu_alias;
#define vtoy_tip_image_file 0
#define vtoy_tip_directory 1
typedef struct menu_tip
{
int type;
int pathlen;
char isopath[256];
char tip1[1024];
@@ -1063,7 +1066,7 @@ int ventoy_fill_windows_rtdata(void *buf, char *isopath);
int ventoy_plugin_get_persistent_chunklist(const char *isopath, int index, ventoy_img_chunk_list *chunk_list);
const char * ventoy_plugin_get_injection(const char *isopath);
const char * ventoy_plugin_get_menu_alias(int type, const char *isopath);
const menu_tip * ventoy_plugin_get_menu_tip(const char *isopath);
const menu_tip * ventoy_plugin_get_menu_tip(int type, const char *isopath);
const char * ventoy_plugin_get_menu_class(int type, const char *name, const char *path);
int ventoy_plugin_check_memdisk(const char *isopath);
int ventoy_plugin_get_image_list_index(int type, const char *name);
@@ -1074,6 +1077,8 @@ int ventoy_get_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, gr
int ventoy_check_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start);
void ventoy_plugin_dump_persistence(void);
grub_err_t ventoy_cmd_set_theme(grub_extcmd_context_t ctxt, int argc, char **args);
grub_err_t ventoy_cmd_set_theme_path(grub_extcmd_context_t ctxt, int argc, char **args);
grub_err_t ventoy_cmd_select_theme_cfg(grub_extcmd_context_t ctxt, int argc, char **args);
grub_err_t ventoy_cmd_plugin_check_json(grub_extcmd_context_t ctxt, int argc, char **args);
grub_err_t ventoy_cmd_check_password(grub_extcmd_context_t ctxt, int argc, char **args);
grub_err_t ventoy_cmd_linux_get_main_initrd_index(grub_extcmd_context_t ctxt, int argc, char **args);
@@ -1085,6 +1090,7 @@ int ventoy_get_disk_guid(const char *filename, grub_uint8_t *guid, grub_uint8_t
grub_err_t ventoy_cmd_unix_reset(grub_extcmd_context_t ctxt, int argc, char **args);
grub_err_t ventoy_cmd_unix_replace_conf(grub_extcmd_context_t ctxt, int argc, char **args);
grub_err_t ventoy_cmd_unix_replace_ko(grub_extcmd_context_t ctxt, int argc, char **args);
grub_err_t ventoy_cmd_unix_ko_fillmap(grub_extcmd_context_t ctxt, int argc, char **args);
grub_err_t ventoy_cmd_unix_fill_image_desc(grub_extcmd_context_t ctxt, int argc, char **args);
grub_err_t ventoy_cmd_unix_gzip_newko(grub_extcmd_context_t ctxt, int argc, char **args);
grub_err_t ventoy_cmd_unix_freebsd_ver(grub_extcmd_context_t ctxt, int argc, char **args);
@@ -1125,5 +1131,27 @@ int ventoy_chain_file_read(const char *path, int offset, int len, void *buf);
extern ventoy_grub_param *g_grub_param;
#pragma pack(1)
#define VENTOY_UNIX_SEG_MAGIC0 0x11223344
#define VENTOY_UNIX_SEG_MAGIC1 0x55667788
#define VENTOY_UNIX_SEG_MAGIC2 0x99aabbcc
#define VENTOY_UNIX_SEG_MAGIC3 0xddeeff00
#define VENTOY_UNIX_MAX_SEGNUM 40960
struct g_ventoy_seg {
grub_uint64_t seg_start_bytes;
grub_uint64_t seg_end_bytes;
};
struct g_ventoy_map{
grub_uint32_t magic1[4];
grub_uint32_t magic2[4];
grub_uint64_t segnum;
grub_uint64_t disksize;
grub_uint8_t diskuuid[16];
struct g_ventoy_seg seglist[VENTOY_UNIX_MAX_SEGNUM];
grub_uint32_t magic3[4];
};
#pragma pack()
#endif /* __VENTOY_DEF_H__ */

View File

@@ -57,6 +57,7 @@ static auto_memdisk *g_auto_memdisk_head = NULL;
static image_list *g_image_list_head = NULL;
static conf_replace *g_conf_replace_head = NULL;
static int g_theme_id = 0;
static int g_theme_num = 0;
static theme_list *g_theme_head = NULL;
static int g_theme_random = vtoy_theme_random_boot_second;
@@ -281,6 +282,7 @@ static int ventoy_plugin_theme_check(VTOY_JSON *json, const char *isodisk)
static int ventoy_plugin_theme_entry(VTOY_JSON *json, const char *isodisk)
{
const char *value;
char val[64];
char filepath[256];
VTOY_JSON *node = NULL;
theme_list *tail = NULL;
@@ -366,6 +368,18 @@ static int ventoy_plugin_theme_entry(VTOY_JSON *json, const char *isodisk)
}
}
}
grub_snprintf(val, sizeof(val), "%d", g_theme_num);
grub_env_set("VTOY_THEME_COUNT", val);
grub_env_export("VTOY_THEME_COUNT");
if (g_theme_num > 0)
{
vtoy_json_get_int(json->pstChild, "default_file", &g_theme_id);
if (g_theme_id > g_theme_num || g_theme_id < 0)
{
g_theme_id = 0;
}
}
value = vtoy_json_get_string_ex(json->pstChild, "gfxmode");
if (value)
@@ -1478,6 +1492,7 @@ static int ventoy_plugin_menualias_entry(VTOY_JSON *json, const char *isodisk)
static int ventoy_plugin_menutip_check(VTOY_JSON *json, const char *isodisk)
{
int type;
const char *path = NULL;
const char *tip = NULL;
VTOY_JSON *pNode = NULL;
@@ -1511,20 +1526,41 @@ static int ventoy_plugin_menutip_check(VTOY_JSON *json, const char *isodisk)
pNode = vtoy_json_find_item(json->pstChild, JSON_TYPE_ARRAY, "tips");
for (pNode = pNode->pstChild; pNode; pNode = pNode->pstNext)
{
type = vtoy_tip_image_file;
path = vtoy_json_get_string_ex(pNode->pstChild, "image");
if (!path)
{
path = vtoy_json_get_string_ex(pNode->pstChild, "dir");
type = vtoy_tip_directory;
}
if (path && path[0] == '/')
{
if (grub_strchr(path, '*'))
if (vtoy_tip_image_file == type)
{
grub_printf("image: <%s> [ * ]\n", path);
}
else if (ventoy_check_file_exist("%s%s", isodisk, path))
{
grub_printf("image: <%s> [ OK ]\n", path);
if (grub_strchr(path, '*'))
{
grub_printf("image: <%s> [ * ]\n", path);
}
else if (ventoy_is_file_exist("%s%s", isodisk, path))
{
grub_printf("image: <%s> [ OK ]\n", path);
}
else
{
grub_printf("image: <%s> [ NOT EXIST ]\n", path);
}
}
else
{
grub_printf("image: <%s> [ NOT EXIST ]\n", path);
if (ventoy_is_dir_exist("%s%s", isodisk, path))
{
grub_printf("dir: <%s> [ OK ]\n", path);
}
else
{
grub_printf("dir: <%s> [ NOT EXIST ]\n", path);
}
}
tip = vtoy_json_get_string_ex(pNode->pstChild, "tip");
@@ -1558,6 +1594,7 @@ static int ventoy_plugin_menutip_check(VTOY_JSON *json, const char *isodisk)
static int ventoy_plugin_menutip_entry(VTOY_JSON *json, const char *isodisk)
{
int type;
const char *path = NULL;
const char *tip = NULL;
VTOY_JSON *pNode = NULL;
@@ -1610,12 +1647,20 @@ static int ventoy_plugin_menutip_entry(VTOY_JSON *json, const char *isodisk)
for (pNode = pNode->pstChild; pNode; pNode = pNode->pstNext)
{
type = vtoy_tip_image_file;
path = vtoy_json_get_string_ex(pNode->pstChild, "image");
if (!path)
{
path = vtoy_json_get_string_ex(pNode->pstChild, "dir");
type = vtoy_tip_directory;
}
if (path && path[0] == '/')
{
node = grub_zalloc(sizeof(menu_tip));
if (node)
{
node->type = type;
node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", path);
tip = vtoy_json_get_string_ex(pNode->pstChild, "tip");
@@ -2399,7 +2444,9 @@ static int ventoy_parse_plugin_config(VTOY_JSON *json, const char *isodisk)
grub_err_t ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt, int argc, char **args)
{
int ret = 0;
int offset = 0;
char *buf = NULL;
grub_uint8_t *code = NULL;
grub_file_t file;
VTOY_JSON *json = NULL;
@@ -2436,9 +2483,25 @@ grub_err_t ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt, int argc, char **a
return 1;
}
code = (grub_uint8_t *)buf;
if (code[0] == 0xef && code[1] == 0xbb && code[2] == 0xbf)
{
offset = 3; /* Skip UTF-8 BOM */
}
else if ((code[0] == 0xff && code[1] == 0xfe) || (code[0] == 0xfe && code[1] == 0xff))
{
grub_env_set("VTOY_PLUGIN_SYNTAX_ERROR", "1");
grub_env_export("VTOY_PLUGIN_SYNTAX_ERROR");
ret = vtoy_json_parse(json, buf);
grub_env_set("VTOY_PLUGIN_ENCODE_ERROR", "1");
grub_env_export("VTOY_PLUGIN_ENCODE_ERROR");
debug("Failed to parse json string %d\n", ret);
grub_free(buf);
return 1;
}
ret = vtoy_json_parse(json, buf + offset);
if (ret)
{
grub_env_set("VTOY_PLUGIN_SYNTAX_ERROR", "1");
@@ -2736,7 +2799,7 @@ const char * ventoy_plugin_get_menu_alias(int type, const char *isopath)
return NULL;
}
const menu_tip * ventoy_plugin_get_menu_tip(const char *isopath)
const menu_tip * ventoy_plugin_get_menu_tip(int type, const char *isopath)
{
int len;
menu_tip *node = NULL;
@@ -2749,7 +2812,8 @@ const menu_tip * ventoy_plugin_get_menu_tip(const char *isopath)
len = (int)grub_strlen(isopath);
for (node = g_menu_tip_head; node; node = node->next)
{
if (node->pathlen == len && ventoy_strcmp(node->isopath, isopath) == 0)
if (node->type == type && node->pathlen &&
node->pathlen == len && ventoy_strcmp(node->isopath, isopath) == 0)
{
return node;
}
@@ -3227,6 +3291,65 @@ end:
return 0;
}
grub_err_t ventoy_cmd_select_theme_cfg(grub_extcmd_context_t ctxt, int argc, char **args)
{
int pos = 0;
int bufsize = 0;
char *name = NULL;
char *buf = NULL;
theme_list *node = NULL;
(void)argc;
(void)args;
(void)ctxt;
if (g_theme_single_file[0])
{
return 0;
}
if (g_theme_num < 2)
{
return 0;
}
bufsize = (g_theme_num + 1) * 1024;
buf = grub_malloc(bufsize);
if (!buf)
{
return 0;
}
for (node = g_theme_head; node; node = node->next)
{
name = grub_strstr(node->theme.path, ")/");
if (name)
{
name++;
}
else
{
name = node->theme.path;
}
pos += grub_snprintf(buf + pos, bufsize - pos,
"menuentry \"%s\" --class=debug_theme_item --class=debug_theme_select --class=F5tool {\n"
"vt_set_theme_path \"%s\"\n"
"}\n",
name, node->theme.path);
}
pos += grub_snprintf(buf + pos, bufsize - pos,
"menuentry 'Return to previous menu [Esc]' --class=vtoyret VTOY_RET {\n"
"echo 'Return ...'\n"
"}\n");
grub_script_execute_sourcecode(buf);
grub_free(buf);
return 0;
}
grub_err_t ventoy_cmd_set_theme(grub_extcmd_context_t ctxt, int argc, char **args)
{
grub_uint32_t i = 0;
@@ -3251,6 +3374,17 @@ grub_err_t ventoy_cmd_set_theme(grub_extcmd_context_t ctxt, int argc, char **arg
{
goto end;
}
if (g_theme_id > 0 && g_theme_id <= g_theme_num)
{
for (i = 0; i < (grub_uint32_t)(g_theme_id - 1) && node; i++)
{
node = node->next;
}
grub_env_set("theme", node->theme.path);
goto end;
}
grub_memset(&datetime, 0, sizeof(datetime));
grub_get_datetime(&datetime);
@@ -3282,7 +3416,25 @@ grub_err_t ventoy_cmd_set_theme(grub_extcmd_context_t ctxt, int argc, char **arg
grub_env_set("theme", node->theme.path);
end:
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
extern char g_ventoy_theme_path[256];
grub_err_t ventoy_cmd_set_theme_path(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)argc;
(void)ctxt;
if (argc == 0)
{
g_ventoy_theme_path[0] = 0;
}
else
{
grub_snprintf(g_ventoy_theme_path, sizeof(g_ventoy_theme_path), "%s", args[0]);
}
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}

View File

@@ -47,6 +47,11 @@ char *g_conf_new_data = NULL;
int g_mod_new_len = 0;
char *g_mod_new_data = NULL;
int g_mod_search_magic = 0;
int g_ko_fillmap_len = 0;
char *g_ko_fillmap_data = NULL;
grub_uint64_t g_mod_override_offset = 0;
grub_uint64_t g_conf_override_offset = 0;
@@ -82,6 +87,15 @@ static grub_uint32_t ventoy_unix_get_override_chunk_count(void)
{
count++;
}
if (g_ko_fillmap_len > 0)
{
count += (g_ko_fillmap_len / 512);
if ((g_ko_fillmap_len % 512) > 0)
{
count++;
}
}
return count;
}
@@ -121,15 +135,50 @@ static grub_uint32_t ventoy_unix_get_virt_chunk_size(void)
return size;
}
static void ventoy_unix_fill_override_data( grub_uint64_t isosize, void *override)
static void ventoy_unix_fill_map_data(ventoy_chain_head *chain, struct g_ventoy_map *map)
{
grub_uint32_t i;
ventoy_img_chunk *chunk = NULL;
debug("Fill unix map data: <%llu> <%u> %p\n",
(unsigned long long)chain->os_param.vtoy_disk_size, g_img_chunk_list.cur_chunk, map);
map->magic1[0] = map->magic2[0] = VENTOY_UNIX_SEG_MAGIC0;
map->magic1[1] = map->magic2[1] = VENTOY_UNIX_SEG_MAGIC1;
map->magic1[2] = map->magic2[2] = VENTOY_UNIX_SEG_MAGIC2;
map->magic1[3] = map->magic2[3] = VENTOY_UNIX_SEG_MAGIC3;
map->disksize = chain->os_param.vtoy_disk_size;
grub_memcpy(map->diskuuid, chain->os_param.vtoy_disk_guid, 16);
map->segnum = g_img_chunk_list.cur_chunk;
if (g_img_chunk_list.cur_chunk > VENTOY_UNIX_MAX_SEGNUM)
{
debug("####[FAIL] Too many segments for the ISO file %u\n", g_img_chunk_list.cur_chunk);
map->segnum = VENTOY_UNIX_MAX_SEGNUM;
}
for (i = 0; i < (grub_uint32_t)(map->segnum); i++)
{
chunk = g_img_chunk_list.chunk + i;
map->seglist[i].seg_start_bytes = chunk->disk_start_sector * 512ULL;
map->seglist[i].seg_end_bytes = (chunk->disk_end_sector + 1) * 512ULL;
}
}
static void ventoy_unix_fill_override_data( grub_uint64_t isosize, ventoy_chain_head *chain)
{
int i;
int left;
char *data = NULL;
grub_uint64_t offset;
grub_uint64_t sector;
ventoy_override_chunk *cur;
ventoy_iso9660_override *dirent;
sector = (isosize + 2047) / 2048;
cur = (ventoy_override_chunk *)override;
cur = (ventoy_override_chunk *)((char *)chain + chain->override_chunk_offset);
if (g_conf_new_len > 0)
{
@@ -142,12 +191,12 @@ static void ventoy_unix_fill_override_data( grub_uint64_t isosize, void *over
dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
dirent->size_be = grub_swap_bytes32(dirent->size);
sector += (dirent->size + 2047) / 2048;
cur++;
}
if (g_mod_new_len > 0)
{
/* mod.ko */
cur++;
cur->img_offset = g_mod_override_offset;
cur->override_size = sizeof(ventoy_iso9660_override);
dirent = (ventoy_iso9660_override *)cur->override_data;
@@ -156,6 +205,37 @@ static void ventoy_unix_fill_override_data( grub_uint64_t isosize, void *over
dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
dirent->size_be = grub_swap_bytes32(dirent->size);
sector += (dirent->size + 2047) / 2048;
cur++;
}
if (g_ko_fillmap_len > 0)
{
data = g_ko_fillmap_data;
offset = g_mod_override_offset;
ventoy_unix_fill_map_data(chain, (struct g_ventoy_map *)data);
for (i = 0; i < g_ko_fillmap_len / 512; i++)
{
cur->img_offset = offset;
cur->override_size = 512;
grub_memcpy(cur->override_data, data, 512);
offset += 512;
data += 512;
cur++;
}
left = (g_ko_fillmap_len % 512);
if (left > 0)
{
cur->img_offset = offset;
cur->override_size = left;
grub_memcpy(cur->override_data, data, left);
offset += left;
cur++;
}
}
return;
@@ -182,6 +262,11 @@ static void ventoy_unix_fill_virt_data( grub_uint64_t isosize, ventoy_chain_h
if (g_mod_new_len > 0)
{
if (g_mod_search_magic > 0)
{
ventoy_unix_fill_map_data(chain, (struct g_ventoy_map *)(g_mod_new_data + g_mod_search_magic));
}
ventoy_unix_fill_virt(g_mod_new_data, g_mod_new_len);
}
@@ -210,6 +295,12 @@ static int ventoy_freebsd_append_conf(char *buf, const char *isopath)
vtoy_ssprintf(buf, pos, "ventoy_load=\"%s\"\n", "YES");
vtoy_ssprintf(buf, pos, "ventoy_name=\"%s\"\n", g_ko_mod_path);
if (g_mod_search_magic)
{
debug("hint.ventoy NO need\n");
goto out;
}
disk = isofile->device->disk;
ventoy_get_disk_guid(isofile->name, disk_guid, disk_sig);
@@ -232,8 +323,8 @@ static int ventoy_freebsd_append_conf(char *buf, const char *isopath)
(ulonglong)((chunk->disk_end_sector + 1) * 512));
}
out:
grub_file_close(isofile);
return pos;
}
@@ -258,13 +349,16 @@ grub_err_t ventoy_cmd_unix_reset(grub_extcmd_context_t ctxt, int argc, char **ar
(void)argc;
(void)args;
g_mod_search_magic = 0;
g_conf_new_len = 0;
g_mod_new_len = 0;
g_mod_override_offset = 0;
g_conf_override_offset = 0;
g_ko_fillmap_len = 0;
check_free(g_mod_new_data, grub_free);
check_free(g_conf_new_data, grub_free);
check_free(g_ko_fillmap_data, grub_free);
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
@@ -624,6 +718,27 @@ grub_err_t ventoy_cmd_unix_replace_conf(grub_extcmd_context_t ctxt, int argc, ch
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static int ventoy_unix_search_magic(char *data, int len)
{
int i;
grub_uint32_t *magic = NULL;
for (i = 0; i < len; i += 65536)
{
magic = (grub_uint32_t *)(data + i);
if (magic[0] == VENTOY_UNIX_SEG_MAGIC0 && magic[1] == VENTOY_UNIX_SEG_MAGIC1 &&
magic[2] == VENTOY_UNIX_SEG_MAGIC2 && magic[3] == VENTOY_UNIX_SEG_MAGIC3)
{
debug("unix find search magic at 0x%x loop:%d\n", i, (i >> 16));
g_mod_search_magic = i;
return 0;
}
}
debug("unix can not find search magic\n");
return 1;
}
grub_err_t ventoy_cmd_unix_replace_ko(grub_extcmd_context_t ctxt, int argc, char **args)
{
char *data;
@@ -673,10 +788,73 @@ grub_err_t ventoy_cmd_unix_replace_ko(grub_extcmd_context_t ctxt, int argc, char
g_mod_new_data = data;
g_mod_new_len = (int)file->size;
ventoy_unix_search_magic(g_mod_new_data, g_mod_new_len);
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
grub_err_t ventoy_cmd_unix_ko_fillmap(grub_extcmd_context_t ctxt, int argc, char **args)
{
int i;
grub_file_t file;
grub_uint32_t magic[4];
grub_uint32_t len;
(void)ctxt;
if (argc != 1)
{
debug("Fillmap ko invalid argc %d\n", argc);
return 1;
}
debug("Fillmap ko %s\n", args[0]);
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "(loop)%s", args[0]);
if (file)
{
grub_file_read(file, magic, 4); /* read for trigger */
g_mod_override_offset = grub_iso9660_get_last_read_pos(file);
}
else
{
debug("Can't find replace ko file from %s\n", args[0]);
return 1;
}
for (i = 0; i < (int)(file->size); i += 65536)
{
magic[0] = 0;
grub_file_seek(file, i);
grub_file_read(file, magic, sizeof(magic));
if (magic[0] == VENTOY_UNIX_SEG_MAGIC0 && magic[1] == VENTOY_UNIX_SEG_MAGIC1 &&
magic[2] == VENTOY_UNIX_SEG_MAGIC2 && magic[3] == VENTOY_UNIX_SEG_MAGIC3)
{
debug("unix find search magic at 0x%x loop:%d\n", i, (i >> 16));
g_mod_override_offset += i;
break;
}
}
len = (grub_uint32_t)OFFSET_OF(struct g_ventoy_map, seglist) +
(sizeof(struct g_ventoy_seg) * g_img_chunk_list.cur_chunk);
g_ko_fillmap_len = (int)len;
g_ko_fillmap_data = grub_malloc(len);
if (!g_ko_fillmap_data)
{
g_ko_fillmap_len = 0;
debug("Failed to malloc fillmap data\n");
}
debug("Fillmap ko segnum:%u, override len:%u data:%p\n", g_img_chunk_list.cur_chunk, len, g_ko_fillmap_data);
grub_file_close(file);
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
grub_err_t ventoy_cmd_unix_fill_image_desc(grub_extcmd_context_t ctxt, int argc, char **args)
{
int i;
@@ -908,7 +1086,7 @@ grub_err_t ventoy_cmd_unix_chain_data(grub_extcmd_context_t ctxt, int argc, char
/* part 4: override chunk */
chain->override_chunk_offset = chain->img_chunk_offset + img_chunk_size;
chain->override_chunk_num = override_count;
ventoy_unix_fill_override_data(isosize, (char *)chain + chain->override_chunk_offset);
ventoy_unix_fill_override_data(isosize, chain);
/* part 5: virt chunk */
chain->virt_chunk_offset = chain->override_chunk_offset + override_size;

View File

@@ -29,13 +29,21 @@ for i in 0 1 2 3 4 5 6 7 8 9; do
fi
done
ventoy_extract_vtloopex ${vtdiskname}2 crux
# no need since 3.6.1
$BUSYBOX_PATH/modprobe dax > /dev/null 2>&1
$BUSYBOX_PATH/modprobe dm-mod > /dev/null 2>&1
if $GREP -q 'device-mapper' /proc/devices; then
vtlog "dm-mod module check success ..."
else
vtlog "Need to load dm-mod module ..."
ventoy_extract_vtloopex ${vtdiskname}2 crux
vtKver=$(uname -r)
vtLoopExDir=$VTOY_PATH/vtloopex/crux/vtloopex
vtKver=$(uname -r)
vtLoopExDir=$VTOY_PATH/vtloopex/crux/vtloopex
ventoy_check_install_module_xz $vtLoopExDir/dm-mod/$vtKver/64/dax.ko
ventoy_check_install_module_xz $vtLoopExDir/dm-mod/$vtKver/64/dm-mod.ko
ventoy_check_install_module_xz $vtLoopExDir/dm-mod/$vtKver/64/dax.ko
ventoy_check_install_module_xz $vtLoopExDir/dm-mod/$vtKver/64/dm-mod.ko
fi
ventoy_udev_disk_common_hook "${vtdiskname#/dev/}2"

View File

@@ -0,0 +1,82 @@
#!/ventoy/busybox/sh
#************************************************************************************
# Copyright (c) 2020, longpanda <admin@ventoy.net>
#
# 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 3 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, see <http://www.gnu.org/licenses/>.
#
#************************************************************************************
. /ventoy/hook/ventoy-hook-lib.sh
vtlog "####### $0 $* ########"
VTPATH_OLD=$PATH; PATH=$BUSYBOX_PATH:$VTOY_PATH/tool:$PATH
ventoy_os_install_dmsetup_by_fuse() {
vtlog "ventoy_os_install_dmsetup_by_fuse $*"
mkdir -p $VTOY_PATH/mnt/fuse $VTOY_PATH/mnt/iso $VTOY_PATH/mnt/squashfs
vtoydm -p -f $VTOY_PATH/ventoy_image_map -d $1 > $VTOY_PATH/ventoy_dm_table
vtoy_fuse_iso -f $VTOY_PATH/ventoy_dm_table -m $VTOY_PATH/mnt/fuse
mount -t iso9660 $VTOY_PATH/mnt/fuse/ventoy.iso $VTOY_PATH/mnt/iso
mount -t squashfs $VTOY_PATH/mnt/iso/minios/01-core*.sb $VTOY_PATH/mnt/squashfs
KoName=$(ls $VTOY_PATH/mnt/squashfs/lib/modules/$2/kernel/drivers/md/dm-mod.ko*)
vtlog "insmod $KoName"
insmod $KoName
umount $VTOY_PATH/mnt/squashfs
umount $VTOY_PATH/mnt/iso
umount $VTOY_PATH/mnt/fuse
}
ventoy_os_install_dmsetup() {
vtlog "ventoy_os_install_dmsetup"
if grep -q 'device-mapper' /proc/devices; then
vtlog "device-mapper module already loaded"
return;
fi
vtKerVer=$(uname -r)
if modprobe fuse 2>>$VTLOG; then
ventoy_os_install_dmsetup_by_fuse $1 $vtKerVer
fi
}
vtdiskname=$(get_ventoy_disk_name)
if [ "$vtdiskname" = "unknown" ]; then
vtlog "ventoy disk not found"
PATH=$VTPATH_OLD
exit 0
fi
if check_usb_disk_ready "$vtdiskname"; then
vtlog "check_usb_disk_ready ok"
else
vtlog "check_usb_disk_ready error"
PATH=$VTPATH_OLD
exit 0
fi
ventoy_os_install_dmsetup $vtdiskname
ventoy_udev_disk_common_hook "${vtdiskname#/dev/}2" "noreplace"
PATH=$VTPATH_OLD

View File

@@ -0,0 +1,24 @@
#!/ventoy/busybox/sh
#************************************************************************************
# Copyright (c) 2020, longpanda <admin@ventoy.net>
#
# 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 3 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, see <http://www.gnu.org/licenses/>.
#
#************************************************************************************
if [ -f /lib/livekitlib ] && $GREP -q 'debug_log.*find_data_try' /lib/livekitlib; then
$SED "/debug_log.*find_data_try/a\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/debian/minios-disk.sh" -i /lib/livekitlib
else
$SED "/find_data/i\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/debian/minios-disk.sh" -i /init
fi

View File

@@ -56,6 +56,10 @@ ventoy_get_debian_distro() {
echo 'slax'; return
fi
if $GREP -q 'minios/' /proc/cmdline; then
echo 'minios'; return
fi
if $GREP -q 'PVE ' /proc/version; then
echo 'pve'; return
fi

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
size=1024
fstype=ext4
@@ -7,13 +7,14 @@ config=''
outputfile=persistence.dat
print_usage() {
echo 'Usage: CreatePersistentImg.sh [ -s size ] [ -t fstype ] [ -l LABEL ] [ -c CFG ]'
echo 'Usage: sudo ./CreatePersistentImg.sh [ -s size ] [ -t fstype ] [ -l LABEL ] [ -c CFG ] [ -e ]'
echo ' OPTION: (optional)'
echo ' -s size in MB, default is 1024'
echo ' -t filesystem type, default is ext4 ext2/ext3/ext4/xfs are supported now'
echo ' -l label, default is casper-rw'
echo ' -c configfile name inside the persistence file. File content is "/ union"'
echo ' -o outputfile name, default is persistence.dat'
echo ' -e enable encryption, disabled by default (only few distros support this)'
echo ''
}
@@ -33,6 +34,9 @@ while [ -n "$1" ]; do
elif [ "$1" = "-o" ]; then
shift
outputfile=$1
elif [ "$1" = "-e" ]; then
read -s -p "Encryption passphrase: " passphrase
echo
elif [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
print_usage
exit 0
@@ -86,6 +90,13 @@ freeloop=$(losetup -f)
losetup $freeloop "$outputfile"
if [ ! -z "$passphrase" ]; then
printf "$passphrase" | cryptsetup -q --verbose luksFormat $freeloop -
printf "$passphrase" | cryptsetup -q --verbose luksOpen $freeloop persist_decrypted -
_freeloop=$freeloop
freeloop="/dev/mapper/persist_decrypted"
fi
mkfs -t $fstype $fsopt -L $label $freeloop
sync
@@ -104,4 +115,9 @@ if [ -n "$config" ]; then
rm -rf ./persist_tmp_mnt
fi
if [ ! -z "$passphrase" ]; then
cryptsetup luksClose $freeloop
freeloop=$_freeloop
fi
losetup -d $freeloop

View File

@@ -22,6 +22,11 @@ Please refer https://www.ventoy.net/en/doc_start.html for details.
2. open your browser and visit http://127.0.0.1:24680
========== VentoyPlugson.sh ===============
1. sudo sh VentoyPlugson.sh
2. open your browser and visit http://127.0.0.1:24681
========= VentoyGUI ===================
VentoyGUI is native GUI program for Linux (GTK/QT)
1. Just double-click the file (e.g. VentoyGUI.x86_64)

Binary file not shown.

View File

@@ -46,23 +46,25 @@ echo "############# Ventoy2Disk $* [$TOOLDIR] ################" >> ./log.txt
date >> ./log.txt
#decompress tool
if [ -f ./tool/$TOOLDIR/ash ]; then
echo "no need to decompress tools" >> ./log.txt
else
cd ./tool/$TOOLDIR
echo "decompress tools" >> ./log.txt
cd ./tool/$TOOLDIR
ls *.xz > /dev/null 2>&1
if [ $? -eq 0 ]; then
[ -f ./xzcat ] && chmod +x ./xzcat
for file in $(ls *.xz); do
echo "decompress $file" >> ./log.txt
xzcat $file > ${file%.xz}
[ -f ./${file%.xz} ] && chmod +x ./${file%.xz}
[ -f ./$file ] && rm -f ./$file
done
cd ../../
chmod +x -R ./tool/$TOOLDIR
fi
cd ../../
chmod +x -R ./tool/$TOOLDIR
if [ -f /bin/bash ]; then
/bin/bash ./tool/VentoyWorker.sh $*
else

Binary file not shown.

Binary file not shown.

Binary file not shown.

218
INSTALL/VentoyPlugson.sh Normal file
View File

@@ -0,0 +1,218 @@
#!/bin/sh
. ./tool/ventoy_lib.sh
print_usage() {
echo 'Usage: sudo sh VentoyPlugson.sh [OPTION] /dev/sdX'
echo ' OPTION: (optional)'
echo ' -H x.x.x.x http server IP address (default is 127.0.0.1)'
echo ' -P PORT http server PORT (default is 24681)'
echo ' -h print this help'
echo ''
}
uid=$(id -u)
if [ $uid -ne 0 ]; then
echo "Please use sudo or run the script as root."
exit 1
fi
OLDDIR=$(pwd)
machine=$(uname -m)
if echo $machine | egrep -q 'aarch64|arm64'; then
TOOLDIR=aarch64
elif echo $machine | egrep -q 'x86_64|amd64'; then
TOOLDIR=x86_64
elif echo $machine | egrep -q 'mips64'; then
TOOLDIR=mips64el
elif echo $machine | egrep -q 'i[3-6]86'; then
TOOLDIR=i386
else
echo "Unsupported machine type $machine"
exit 1
fi
if ! [ -f "$OLDDIR/tool/plugson.tar.xz" ]; then
echo "Please run under the correct directory!"
exit 1
fi
echo "############# VentoyPlugson $* [$TOOLDIR] ################" >> ./VentoyPlugson.log
date >> ./VentoyPlugson.log
echo "decompress tools" >> ./VentoyPlugson.log
cd ./tool/$TOOLDIR
ls *.xz > /dev/null 2>&1
if [ $? -eq 0 ]; then
[ -f ./xzcat ] && chmod +x ./xzcat
for file in $(ls *.xz); do
echo "decompress $file" >> ./VentoyPlugson.log
xzcat $file > ${file%.xz}
[ -f ./${file%.xz} ] && chmod +x ./${file%.xz}
[ -f ./$file ] && rm -f ./$file
done
fi
cd ../../
chmod +x -R ./tool/$TOOLDIR
if ! [ -f "$OLDDIR/tool/$TOOLDIR/Plugson" ]; then
echo "$OLDDIR/tool/$TOOLDIR/Plugson does not exist!"
exit 1
fi
PATH=./tool/$TOOLDIR:$PATH
HOST="127.0.0.1"
PORT=24681
while [ -n "$1" ]; do
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
print_usage
exit 0
elif [ "$1" = "-H" ]; then
shift
if echo $1 | grep -q '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*'; then
HOST="$1"
else
echo "Invalid host $1"
exit 1
fi
elif [ "$1" = "-P" ]; then
shift
if [ $1 -gt 0 -a $1 -le 65535 ]; then
PORT="$1"
else
echo "Invalid port $1"
exit 1
fi
else
DISK=$1
fi
shift
done
if [ -z "$DISK" ]; then
print_usage
exit 0
fi
if ps -ef | grep "tool/$TOOLDIR/Plugson.*$HOST.*$PORT" | grep -q -v grep; then
echo "Another ventoy server is running now, please close it first."
exit 1
fi
if echo $DISK | grep -q "[a-z]d[a-z][1-9]"; then
DISK=${DISK:0:-1}
fi
if echo $DISK | egrep -q "/dev/nvme|/dev/mmcblk/dev/nbd"; then
if echo $DISK | grep -q "p[1-9]$"; then
DISK=${DISK:0:-2}
fi
fi
if [ ! -b "$DISK" ]; then
echo "$DISK does NOT exist."
exit 1
fi
version=$(get_disk_ventoy_version $DISK)
if [ $? -eq 0 ]; then
echo "Ventoy version in Disk: $version"
vtPart1Type=$(dd if=$DISK bs=1 count=1 skip=450 status=none | hexdump -n1 -e '1/1 "%02X"')
if [ "$vtPart1Type" = "EE" ]; then
echo "Disk Partition Style : GPT"
partstyle=1
else
echo "Disk Partition Style : MBR"
partstyle=0
fi
if check_disk_secure_boot $DISK; then
echo "Secure Boot Support : YES"
secureboot=1
else
echo "Secure Boot Support : NO"
secureboot=0
fi
else
echo "$DISK is NOT Ventoy disk."
exit 1
fi
PART1=$(get_disk_part_name $DISK 1)
if grep -q "^$PART1 " /proc/mounts; then
mtpnt=$(grep "^$PART1 " /proc/mounts | awk '{print $2}')
fstype=$(grep "^$PART1 " /proc/mounts | awk '{print $3}')
if echo $fstype | grep -q -i 'fuse'; then
if hexdump -C -n 16 $PART1 | grep -q -i "EXFAT"; then
fstype="exFAT"
elif hexdump -C -n 16 $PART1 | grep -q -i "NTFS"; then
fstype="NTFS"
fi
fi
echo "$PART1 is mounted at $mtpnt $fstype"
else
echo "$PART1 is NOT mounted, please mount it first!"
exit 1
fi
if [ -d "$mtpnt/ventoy" ]; then
echo "ventoy directory exist OK"
else
echo "create ventoy directory"
mkdir -p "$mtpnt/ventoy"
if [ -d "$mtpnt/ventoy" ]; then
chmod -R 0755 "$mtpnt/ventoy"
else
echo "Failed to create directory $mtpnt/ventoy"
exit 1
fi
fi
#change current directory to Ventoy disk
cd "$mtpnt"
$OLDDIR/tool/$TOOLDIR/Plugson "$HOST" "$PORT" "$OLDDIR" "$DISK" $version "$fstype" $partstyle $secureboot &
wID=$!
sleep 1
if [ -f /proc/$wID/maps ]; then
echo ""
echo "==============================================================="
if [ "$LANG" = "zh_CN.UTF-8" ]; then
echo " Ventoy Plugson Server 已经启动 ..."
echo " 请打开浏览器,访问 http://${HOST}:${PORT}"
else
echo " Ventoy Plugson Server is running ..."
echo " Please open your browser and visit http://${HOST}:${PORT}"
fi
echo "==============================================================="
echo ""
echo "################## Press Ctrl + C to exit #####################"
echo ""
wait $wID
fi
if [ -n "$OLDDIR" ]; then
CURDIR=$(pwd)
if [ "$CURDIR" != "$OLDDIR" ]; then
cd "$OLDDIR"
fi
fi

View File

@@ -38,13 +38,10 @@ sh buildedk.sh >> $LOG 2>&1 || exit 1
#cd $VTOY_PATH/VtoyTool
#sh build.sh || exit 1
#cd $VTOY_PATH/vtoyfat/fat_io_lib
#cd $VTOY_PATH/vtoycli/fat_io_lib
#sh buildlib.sh
#cd $VTOY_PATH/vtoyfat
#sh build.sh || exit 1
#cd $VTOY_PATH/vtoygpt
#cd $VTOY_PATH/vtoycli
#sh build.sh || exit 1
#cd $VTOY_PATH/FUSEISO

View File

@@ -38,6 +38,12 @@ submenu "Screen Display Mode" --class=debug_screen_mode --class=F5tool {
}
}
if [ $VTOY_THEME_COUNT -gt 1 ]; then
submenu "Theme Select" --class=debug_theme_select --class=F5tool {
vt_select_theme_cfg
}
fi
if [ "$grub_platform" != "pc" ]; then
submenu 'Ventoy UEFI Utilities' --class=debug_util --class=F5tool {
menuentry 'Show EFI Drivers' --class=debug_util_efidrv --class=debug_util --class=F5tool {

View File

@@ -129,6 +129,9 @@ function get_os_type {
elif [ -e (loop)/bin/freebsd-version ]; then
set vtoy_os=Unix
set vt_unix_type=FreeBSD
elif [ -e (loop)/boot/kernel/geom_ventoy.ko ]; then
set vtoy_os=Unix
set vt_unix_type=FreeBSD
elif vt_str_begin "$vt_system_id" "DragonFly"; then
set vtoy_os=Unix
set vt_unix_type=DragonFly
@@ -154,9 +157,7 @@ function vt_check_compatible_pe {
#Check for PE without external tools
#set compatible if ISO file is less than 80MB
if [ $vt_chosen_size -gt 33554432 -a $vt_chosen_size -le 83886080 ]; then
set ventoy_compatible=YES
elif [ -e $1/WEPE/WEPE.INI ]; then
set ventoy_compatible=YES
set ventoy_compatible=YES
fi
return
@@ -165,6 +166,8 @@ function vt_check_compatible_pe {
function vt_check_compatible_linux {
if vt_str_begin "$vt_volume_id" "embootkit"; then
set ventoy_compatible=YES
elif [ -e "$1/casper/tinycore.gz" ]; then
set ventoy_compatible=YES
fi
return
@@ -233,6 +236,8 @@ function distro_specify_initrd_file {
vt_linux_specify_initrd_file /initrd.gz
elif [ -e (loop)/slax/boot/initrfs.img ]; then
vt_linux_specify_initrd_file /slax/boot/initrfs.img
elif [ -e (loop)/minios/boot/initrfs.img ]; then
vt_linux_specify_initrd_file /minios/boot/initrfs.img
elif [ -e (loop)/pmagic/initrd.img ]; then
vt_linux_specify_initrd_file /pmagic/initrd.img
elif [ -e (loop)/boot/initrd.xz ]; then
@@ -418,6 +423,11 @@ function ventoy_freebsd_proc {
set vtFreeBsdDistro=FreeBSD
set vt_freebsd_ver=xx
if [ -e (loop)/boot/kernel/geom_ventoy.ko ]; then
vt_unix_ko_fillmap /boot/kernel/geom_ventoy.ko
return
fi
if vt_strstr "$vt_volume_id" "GHOSTBSD"; then
ventoy_get_ghostbsd_ver "$1" "${chosen_path}"
elif vt_strstr "$vt_volume_id" "FREENAS"; then
@@ -713,7 +723,9 @@ function uefi_linux_menu_func {
elif [ -e (loop)/syslinux/alt0/full.cz ]; then
vt_add_replace_file 0 "EFI\\BOOT\\full.cz"
set FirstTryBootFile='@EFI@BOOT@grubx64.efi'
elif vt_str_begin "$vt_volume_id" "SolusLive"; then
vt_add_replace_file 0 "initrd"
fi
@@ -2010,7 +2022,7 @@ function img_unsupport_menuentry {
#############################################################
#############################################################
set VENTOY_VERSION="1.0.58"
set VENTOY_VERSION="1.0.63"
#ACPI not compatible with Window7/8, so disable by default
set VTOY_PARAM_NO_ACPI=1
@@ -2178,12 +2190,19 @@ fi
if [ -n "$VTOY_PLUGIN_SYNTAX_ERROR" ]; then
clear
echo -e "\n Syntax error detected in ventoy.json, please check! \n"
echo -e " ventoy.json 文件中有语法错误,所有配置都不会生效,请检查!\n"
if [ -n "$VTOY_PLUGIN_ENCODE_ERROR" ]; then
echo -e "\n Encoding type for ventoy.json is not supported, please convert to UTF-8.\n"
echo -e " ventoy.json 文件编码格式不支持,请转换为 UTF-8 编码格式!\n"
else
echo -e "\n Syntax error detected in ventoy.json, please check! \n"
echo -e " ventoy.json 文件中有语法错误,所有配置都不会生效,请检查!\n"
fi
echo -e "\n press ENTER to continue (请按 回车 键继续) ..."
read vtInputKey
read vtInputKey
fi
for vtTFile in ventoy.json ventoy_grub.cfg; do
if [ -f $vtoy_efi_part/ventoy/$vtTFile ]; then
clear

View File

@@ -0,0 +1,18 @@
h - Zeigt dieses Hilfe Menu
F1 - Memdisk Modus (Nur für kleine WinPE/LiveCD ISO/IMG)
F2 - Neustarten/Herunterfahren
F3 - Menu wechsel zwischen Baum <-> Listen Ansicht
F4 - Windows/Linux vom lokalem Datenträger starten
F5 - Dienstprogramme
F6 - Benutzerdefiniertes Grub2-Menü laden
F7 - Wechseln zwischen GUI-Modus <-> TEXT-Modus
m - Prüfsummencheck Image Dateien (md5/sha1/sha256/sha512)
Ctrl+w - WIMBOOT Modus (Nur für Standard Windows ISO)
Ctrl+r - Grub2 Modus (Nur für einige Linux distros)
Ctrl+i - Kompatibilitäts Modus (Nur für Fehleranalyse)
Ctrl+u - Lade ISO efi Treiber (Nur für Fehleranalyse, darf nicht offiziel benutzt werden)
Drücke ESC für Zurück ......

View File

@@ -0,0 +1,18 @@
h - この画面を表示する
F1 - 主記憶装置上に記憶域を作成する容量の小さなWinPE・LiveCD専用
F2 - 再起動・電源断
F3 - 表示形式を切り替える(一覧 ↔ 階層)
F4 - 手元の記憶装置にあるOSを起動する
F5 - 諸機能
F6 - Grub2の構成を読み込む
F7 - 操作形式を切り替えるGUI ↔ CUI
m - イメージの検査合計を計算する (md5/sha1/sha256/sha512)
Ctrl+w - WIMBOOTモード標準的なWindows ISO専用
Ctrl+r - Grub2モード一部のLinuxディストリビューション専用
Ctrl+i - 互換モード(開発用)
Ctrl+u - ISO efiドライバーを読み取る開発用非公式
この画面を閉じるにはESCを押してください

View File

@@ -76,6 +76,11 @@ else
terminal_output console
chainloader /EFI/Microsoft/Boot/bootmgfw.efi
boot
elif [ -f ($vtoydev,$partid)/efi/Microsoft/Boot/bootmgfw.efi ]; then
set root=($vtoydev,$partid)
terminal_output console
chainloader /efi/Microsoft/Boot/bootmgfw.efi
boot
fi
else
break
@@ -87,6 +92,10 @@ else
terminal_output console
chainloader /EFI/Microsoft/Boot/bootmgfw.efi
boot
elif search -n -s -f /efi/Microsoft/Boot/bootmgfw.efi; then
terminal_output console
chainloader /efi/Microsoft/Boot/bootmgfw.efi
boot
else
echo "Windows NOT found ..."
fi

View File

@@ -16,6 +16,7 @@ print_usage() {
echo ' -s/-S enable/disable secure boot support (default is disabled)'
echo ' -g use GPT partition style, default is MBR (only for install)'
echo ' -L Label of the 1st exfat partition (default is Ventoy)'
echo ' -n try non-destructive installation (only for install)'
echo ''
}
@@ -28,6 +29,8 @@ while [ -n "$1" ]; do
elif [ "$1" = "-I" ]; then
MODE="install"
FORCE="Y"
elif [ "$1" = "-n" ]; then
NONDESTRUCTIVE="Y"
elif [ "$1" = "-u" ]; then
MODE="update"
elif [ "$1" = "-l" ]; then
@@ -162,7 +165,7 @@ if [ -d ./tmp_mnt ]; then
fi
if [ "$MODE" = "install" ]; then
if [ "$MODE" = "install" -a -z "$NONDESTRUCTIVE" ]; then
vtdebug "install Ventoy ..."
if [ -n "$VTGPT" ]; then
@@ -255,7 +258,10 @@ if [ "$MODE" = "install" ]; then
exit 1
fi
if ! dd if=/dev/zero of=$DISK bs=1 count=512 status=none conv=fsync; then
# check and umount
check_umount_disk "$DISK"
if ! dd if=/dev/zero of=$DISK bs=64 count=512 status=none conv=fsync; then
vterr "Write data to $DISK failed, please check whether it's in use."
exit 1
fi
@@ -281,10 +287,29 @@ if [ "$MODE" = "install" ]; then
PART1=$(get_disk_part_name $DISK 1)
PART2=$(get_disk_part_name $DISK 2)
mkexfatfs -n "$VTNEW_LABEL" -s $cluster_sectors ${PART1}
#clean part2
dd status=none conv=fsync if=/dev/zero of=$DISK bs=512 count=32 seek=$part2_start_sector
vtinfo "writing data to disk ..."
#format part1
wait_and_create_part ${PART1} ${PART2}
if [ -b ${PART1} ]; then
vtinfo "Format partition 1 ${PART1} ..."
mkexfatfs -n "$VTNEW_LABEL" -s $cluster_sectors ${PART1}
if [ $? -ne 0 ]; then
echo "mkexfatfs failed, now retry..."
mkexfatfs -n "$VTNEW_LABEL" -s $cluster_sectors ${PART1}
if [ $? -ne 0 ]; then
echo "######### mkexfatfs failed, exit ########"
exit 1
fi
else
echo "mkexfatfs success"
fi
else
vterr "${PART1} NOT exist"
fi
vtinfo "writing data to disk ..."
dd status=none conv=fsync if=./boot/boot.img of=$DISK bs=1 count=446
if [ -n "$VTGPT" ]; then
@@ -314,51 +339,181 @@ if [ "$MODE" = "install" ]; then
sync
vtinfo "esp partition processing ..."
sleep 1
check_umount_disk "$DISK"
if [ "$SECUREBOOT" != "YES" ]; then
mkdir ./tmp_mnt
vtdebug "mounting part2 ...."
for tt in 1 2 3 4 5; do
if mount ${PART2} ./tmp_mnt > /dev/null 2>&1; then
vtdebug "mounting part2 success"
break
fi
check_umount_disk "$DISK"
sleep 2
done
rm -f ./tmp_mnt/EFI/BOOT/BOOTX64.EFI
rm -f ./tmp_mnt/EFI/BOOT/grubx64.efi
rm -f ./tmp_mnt/EFI/BOOT/BOOTIA32.EFI
rm -f ./tmp_mnt/EFI/BOOT/grubia32.efi
rm -f ./tmp_mnt/EFI/BOOT/MokManager.efi
rm -f ./tmp_mnt/EFI/BOOT/mmia32.efi
rm -f ./tmp_mnt/ENROLL_THIS_KEY_IN_MOKMANAGER.cer
mv ./tmp_mnt/EFI/BOOT/grubx64_real.efi ./tmp_mnt/EFI/BOOT/BOOTX64.EFI
mv ./tmp_mnt/EFI/BOOT/grubia32_real.efi ./tmp_mnt/EFI/BOOT/BOOTIA32.EFI
sync
for tt in 1 2 3; do
if umount ./tmp_mnt; then
vtdebug "umount part2 success"
rm -rf ./tmp_mnt
break
else
vtdebug "umount part2 failed, now retry..."
sleep 1
fi
done
if [ "$SECUREBOOT" != "YES" ]; then
sleep 2
check_umount_disk "$DISK"
vtoycli partresize -s $DISK $part2_start_sector
fi
echo ""
vtinfo "Install Ventoy to $DISK successfully finished."
echo ""
elif [ "$MODE" = "install" -a -n "$NONDESTRUCTIVE" ]; then
vtdebug "non-destructive install Ventoy ..."
version=$(get_disk_ventoy_version $DISK)
if [ $? -eq 0 ]; then
if [ -z "$FORCE" ]; then
vtwarn "$DISK already contains a Ventoy with version $version."
vtwarn "You can not do and don not need non-destructive installation."
vtwarn ""
exit 1
fi
fi
disk_sector_num=$(cat /sys/block/${DISK#/dev/}/size)
disk_size_gb=$(expr $disk_sector_num / 2097152)
if vtoycli partresize -t $DISK; then
OldStyle="GPT"
else
OldStyle="MBR"
fi
#Print disk info
echo "Disk : $DISK"
parted -s $DISK p 2>&1 | grep Model
echo "Size : $disk_size_gb GB"
echo "Style: $OldStyle"
echo ''
vtwarn "Attention:"
vtwarn "Ventoy will try non-destructive installation on $DISK if possible."
echo ""
read -p 'Continue? (y/n) ' Answer
if [ "$Answer" != "y" ]; then
if [ "$Answer" != "Y" ]; then
exit 0
fi
fi
if [ $disk_sector_num -le $VENTOY_SECTOR_NUM ]; then
vterr "No enough space in disk $DISK"
exit 1
fi
PART1=$(get_disk_part_name $DISK 1)
PART2=$(get_disk_part_name $DISK 2)
#Part1 size in MB aligned with 4KB
PART1_SECTORS=$(cat /sys/class/block/${PART1#/dev/}/size)
PART1_4K=$(expr $PART1_SECTORS / 8)
PART1_MB=$(expr $PART1_4K / 256)
PART1_NEW_MB=$(expr $PART1_MB - 32)
echo "$PART1 is ${PART1_MB}MB"
#check partition layout
echo "check partition layout ..."
vtoycli partresize -c $DISK
vtRet=$?
if [ $vtRet -eq 0 ]; then
exit 1
else
# check and umount
check_umount_disk "$DISK"
sleep 1
check_umount_disk "$DISK"
if [ $vtRet -eq 1 ]; then
echo "Free space enough, start install..."
part2_start_sector=$(expr $PART1_SECTORS + 2048)
elif [ $vtRet -eq 2 ]; then
echo "We need to shrink partition 1 firstly ..."
PART1_BLKID=$(blkid $PART1)
blkid $PART1
if echo $PART1_BLKID | egrep -q -i 'TYPE=ntfs|TYPE=.ntfs'; then
echo "Partition 1 contains NTFS filesystem"
which ntfsresize
if [ $? -ne 0 ]; then
echo "###[FAIL] ntfsresize not found. Please install ntfs-3g package."
exit 1
fi
echo "ntfsfix -b -d $PART1 ..."
ntfsfix -b -d $PART1
echo "ntfsresize --size ${PART1_NEW_MB}Mi $PART1 ..."
ntfsresize -f --size ${PART1_NEW_MB}Mi $PART1
if [ $? -ne 0 ]; then
echo "###[FAIL] ntfsresize failed."
exit 1
fi
elif echo $PART1_BLKID | egrep -q -i 'TYPE=ext[2-4]|TYPE=.ext[2-4]'; then
echo "Partition 1 contains EXT filesystem"
which resize2fs
if [ $? -ne 0 ]; then
echo "###[FAIL] resize2fs not found. Please install e2fsprogs package."
exit 1
fi
echo "e2fsck -f $PART1 ..."
e2fsck -f $PART1
echo "resize2fs $PART1 ${PART1_NEW_MB}M ..."
resize2fs $PART1 ${PART1_NEW_MB}M
if [ $? -ne 0 ]; then
echo "###[FAIL] resize2fs failed."
exit 1
fi
else
echo "###[FAIL] Unsupported filesystem in partition 1."
exit 1
fi
sync
PART1_NEW_END_MB=$(expr $PART1_NEW_MB + 1)
part2_start_sector=$(expr $PART1_NEW_END_MB \* 2048)
fi
fi
vtinfo "writing data to disk part2_start=$part2_start_sector ..."
dd status=none conv=fsync if=./boot/boot.img of=$DISK bs=1 count=440
if [ "$OldStyle" = "GPT" ]; then
echo -en '\x22' | dd status=none of=$DISK conv=fsync bs=1 count=1 seek=92
xzcat ./boot/core.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=2014 seek=34
echo -en '\x23' | dd of=$DISK conv=fsync bs=1 count=1 seek=17908 status=none
else
xzcat ./boot/core.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=2047 seek=1
fi
xzcat ./ventoy/ventoy.disk.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=$VENTOY_SECTOR_NUM seek=$part2_start_sector
#test UUID
testUUIDStr=$(vtoy_gen_uuid | hexdump -C)
vtdebug "test uuid: $testUUIDStr"
#disk uuid
vtoy_gen_uuid | dd status=none conv=fsync of=${DISK} seek=384 bs=1 count=16
vtinfo "sync data ..."
sync
vtinfo "esp partition processing ..."
if [ "$SECUREBOOT" != "YES" ]; then
vtoycli partresize -s $DISK $part2_start_sector
fi
vtinfo "update partition table $DISK $part2_start_sector ..."
vtoycli partresize -p $DISK $part2_start_sector
if [ $? -eq 0 ]; then
sync
echo ""
vtinfo "Ventoy non-destructive installation on $DISK successfully finished."
echo ""
else
echo ""
vterr "Ventoy non-destructive installation on $DISK failed."
echo ""
fi
else
vtdebug "update Ventoy ..."
@@ -441,47 +596,13 @@ else
check_umount_disk "$DISK"
xzcat ./ventoy/ventoy.disk.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=$VENTOY_SECTOR_NUM seek=$part2_start
sync
vtinfo "esp partition processing ..."
if [ "$SECUREBOOT" != "YES" ]; then
mkdir ./tmp_mnt
vtdebug "mounting part2 ...."
for tt in 1 2 3 4 5; do
check_umount_disk "$DISK"
if mount ${PART2} ./tmp_mnt > /dev/null 2>&1; then
vtdebug "mounting part2 success"
break
else
vtdebug "mounting part2 failed, now wait and retry..."
fi
sleep 2
done
rm -f ./tmp_mnt/EFI/BOOT/BOOTX64.EFI
rm -f ./tmp_mnt/EFI/BOOT/grubx64.efi
rm -f ./tmp_mnt/EFI/BOOT/BOOTIA32.EFI
rm -f ./tmp_mnt/EFI/BOOT/grubia32.efi
rm -f ./tmp_mnt/EFI/BOOT/MokManager.efi
rm -f ./tmp_mnt/EFI/BOOT/mmia32.efi
rm -f ./tmp_mnt/ENROLL_THIS_KEY_IN_MOKMANAGER.cer
mv ./tmp_mnt/EFI/BOOT/grubx64_real.efi ./tmp_mnt/EFI/BOOT/BOOTX64.EFI
mv ./tmp_mnt/EFI/BOOT/grubia32_real.efi ./tmp_mnt/EFI/BOOT/BOOTIA32.EFI
sync
for tt in 1 2 3; do
if umount ./tmp_mnt > /dev/null 2>&1; then
vtdebug "umount part2 success"
rm -rf ./tmp_mnt
break
else
vtdebug "umount part2 failed, now retry..."
sleep 1
fi
done
sleep 2
check_umount_disk "$DISK"
vtoycli partresize -s $DISK $part2_start
fi
echo ""

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
INSTALL/tool/i386/vtoycli Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -68,10 +68,10 @@ check_tool_work_ok() {
return
fi
if vtoyfat -T; then
vtdebug "vtoyfat test ok ..."
if vtoycli fat -T; then
vtdebug "vtoycli fat test ok ..."
else
vtdebug "vtoyfat test fail ..."
vtdebug "vtoycli fat test fail ..."
ventoy_false
return
fi
@@ -183,7 +183,7 @@ check_disk_secure_boot() {
PART2=$(get_disk_part_name $1 2)
vtoyfat -s $PART2
vtoycli fat -s $PART2
}
get_disk_ventoy_version() {
@@ -195,7 +195,7 @@ get_disk_ventoy_version() {
PART2=$(get_disk_part_name $1 2)
ParseVer=$(vtoyfat $PART2)
ParseVer=$(vtoycli fat $PART2)
if [ $? -eq 0 ]; then
vtdebug "Ventoy version in $PART2 is $ParseVer"
echo $ParseVer
@@ -206,6 +206,48 @@ get_disk_ventoy_version() {
ventoy_false
}
wait_and_create_part() {
vPART1=$1
vPART2=$2
echo 'Wait for partitions ...'
for i in 0 1 2 3 4 5 6 7 8 9; do
if ls -l $vPART1 2>/dev/null | grep -q '^b'; then
if ls -l $vPART2 2>/dev/null | grep -q '^b'; then
break
fi
else
echo "Wait for $vPART1/$vPART2 ..."
sleep 1
fi
done
if ls -l $vPART1 2>/dev/null | grep -q '^b'; then
echo "$vPART1 exist OK"
else
MajorMinor=$(sed "s/:/ /" /sys/class/block/${vPART1#/dev/}/dev)
echo "mknod -m 0660 $vPART1 b $MajorMinor ..."
mknod -m 0660 $vPART1 b $MajorMinor
fi
if ls -l $vPART2 2>/dev/null | grep -q '^b'; then
echo "$vPART2 exist OK"
else
MajorMinor=$(sed "s/:/ /" /sys/class/block/${vPART2#/dev/}/dev)
echo "mknod -m 0660 $vPART2 b $MajorMinor ..."
mknod -m 0660 $vPART2 b $MajorMinor
fi
if ls -l $vPART1 2>/dev/null | grep -q '^b'; then
if ls -l $vPART2 2>/dev/null | grep -q '^b'; then
echo "partition exist OK"
fi
else
echo "[FAIL] $vPART1/$vPART2 does not exist"
exit 1
fi
}
format_ventoy_disk_mbr() {
reserve_mb=$1
DISK=$2
@@ -241,6 +283,11 @@ format_ventoy_disk_mbr() {
vtdebug "part1_start_sector=$part1_start_sector part1_end_sector=$part1_end_sector"
vtdebug "part2_start_sector=$part2_start_sector part2_end_sector=$part2_end_sector"
if [ -e $PART1 ]; then
echo "delete $PART1"
rm -f $PART1
fi
if [ -e $PART2 ]; then
echo "delete $PART2"
rm -f $PART2
@@ -293,27 +340,34 @@ EOF
sleep 3
echo "Done"
echo 'mkfs on disk partitions ...'
for i in 1 2 3 4 5 6 7; do
if [ -b $PART2 ]; then
echo 'Wait for partitions ...'
for i in 0 1 2 3 4 5 6 7 8 9; do
if [ -b $PART1 -a -b $PART2 ]; then
break
else
echo "wait $PART2 ..."
echo "Wait for $PART1/$PART2 ..."
sleep 1
fi
done
if ! [ -b $PART1 ]; then
MajorMinor=$(sed "s/:/ /" /sys/class/block/${PART1#/dev/}/dev)
echo "mknod -m 0660 $PART1 b $MajorMinor ..."
mknod -m 0660 $PART1 b $MajorMinor
fi
if ! [ -b $PART2 ]; then
MajorMinor=$(sed "s/:/ /" /sys/class/block/${PART2#/dev/}/dev)
echo "mknod -m 0660 $PART2 b $MajorMinor ..."
mknod -m 0660 $PART2 b $MajorMinor
if ! [ -b $PART1 ]; then
MajorMinor=$(sed "s/:/ /" /sys/class/block/${PART1#/dev/}/dev)
echo "mknod -m 0660 $PART1 b $MajorMinor ..."
mknod -m 0660 $PART1 b $MajorMinor
fi
mknod -m 0660 $PART2 b $MajorMinor
fi
if [ -b $PART1 -a -b $PART2 ]; then
echo "partition exist OK"
else
echo "[FAIL] $PART1/$PART2 does not exist"
exit 1
fi
echo "create efi fat fs $PART2 ..."
@@ -366,6 +420,11 @@ format_ventoy_disk_gpt() {
vtdebug "part1_start_sector=$part1_start_sector part1_end_sector=$part1_end_sector"
vtdebug "part2_start_sector=$part2_start_sector part2_end_sector=$part2_end_sector"
if [ -e $PART1 ]; then
echo "delete $PART1"
rm -f $PART1
fi
if [ -e $PART2 ]; then
echo "delete $PART2"
rm -f $PART2
@@ -391,7 +450,7 @@ format_ventoy_disk_gpt() {
sync
vtoygpt -f $DISK
vtoycli gpt -f $DISK
sync
udevadm trigger --name-match=$DISK >/dev/null 2>&1
@@ -399,27 +458,33 @@ format_ventoy_disk_gpt() {
sleep 3
echo "Done"
echo 'mkfs on disk partitions ...'
for i in 1 2 3 4 5 6 7; do
if [ -b $PART2 ]; then
echo 'Wait for partitions ...'
for i in 0 1 2 3 4 5 6 7 8 9; do
if [ -b $PART1 -a -b $PART2 ]; then
break
else
echo "wait $PART2 ..."
echo "Wait for $PART1/$PART2 ..."
sleep 1
fi
done
if ! [ -b $PART1 ]; then
MajorMinor=$(sed "s/:/ /" /sys/class/block/${PART1#/dev/}/dev)
echo "mknod -m 0660 $PART1 b $MajorMinor ..."
mknod -m 0660 $PART1 b $MajorMinor
fi
if ! [ -b $PART2 ]; then
MajorMinor=$(sed "s/:/ /" /sys/class/block/${PART2#/dev/}/dev)
echo "mknod -m 0660 $PART2 b $MajorMinor ..."
mknod -m 0660 $PART2 b $MajorMinor
if ! [ -b $PART1 ]; then
MajorMinor=$(sed "s/:/ /" /sys/class/block/${PART1#/dev/}/dev)
echo "mknod -m 0660 $PART1 b $MajorMinor ..."
mknod -m 0660 $PART1 b $MajorMinor
fi
mknod -m 0660 $PART2 b $MajorMinor
fi
if [ -b $PART1 -a -b $PART2 ]; then
echo "partition exist OK"
else
echo "[FAIL] $PART1/$PART2 does not exist"
exit 1
fi
echo "create efi fat fs $PART2 ..."

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
INSTALL/tool/x86_64/vtoycli Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
INSTALL/ventoy/7z/32/7za.xz Normal file

Binary file not shown.

Binary file not shown.

BIN
INSTALL/ventoy/7z/64/7za.xz Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -36,6 +36,11 @@ sh language.sh || exit 1
sh build.sh
cd -
cd ../Plugson
sh build.sh
sh pack.sh
cd -
LOOP=$(losetup -f)
@@ -89,9 +94,9 @@ mkdir -p $tmpmnt/tool
# cp $OPT ./tool/x86_64/mount.exfat-fuse $tmpmnt/tool/mount.exfat-fuse_x86_64
# cp $OPT ./tool/aarch64/mount.exfat-fuse $tmpmnt/tool/mount.exfat-fuse_aarch64
# to save space
cp $OPT ./tool/i386/vtoygpt $tmpmnt/tool/mount.exfat-fuse_i386
cp $OPT ./tool/x86_64/vtoygpt $tmpmnt/tool/mount.exfat-fuse_x86_64
cp $OPT ./tool/aarch64/vtoygpt $tmpmnt/tool/mount.exfat-fuse_aarch64
dd status=none bs=1024 count=16 if=./tool/i386/vtoycli of=$tmpmnt/tool/mount.exfat-fuse_i386
dd status=none bs=1024 count=16 if=./tool/x86_64/vtoycli of=$tmpmnt/tool/mount.exfat-fuse_x86_64
dd status=none bs=1024 count=16 if=./tool/aarch64/vtoycli of=$tmpmnt/tool/mount.exfat-fuse_aarch64
rm -f $tmpmnt/grub/i386-pc/*.img
@@ -112,6 +117,7 @@ cp $OPT ./tool $tmpdir/
rm -f $tmpdir/ENROLL_THIS_KEY_IN_MOKMANAGER.cer
cp $OPT Ventoy2Disk.sh $tmpdir/
cp $OPT VentoyWeb.sh $tmpdir/
cp $OPT VentoyPlugson.sh $tmpdir/
cp $OPT VentoyGUI* $tmpdir/
@@ -121,6 +127,7 @@ cp $OPT CreatePersistentImg.sh $tmpdir/
cp $OPT ExtendPersistentImg.sh $tmpdir/
dos2unix -q $tmpdir/Ventoy2Disk.sh
dos2unix -q $tmpdir/VentoyWeb.sh
dos2unix -q $tmpdir/VentoyPlugson.sh
dos2unix -q $tmpdir/CreatePersistentImg.sh
@@ -159,6 +166,7 @@ find $tmpdir/ -type d -exec chmod 755 "{}" +
find $tmpdir/ -type f -exec chmod 644 "{}" +
chmod +x $tmpdir/Ventoy2Disk.sh
chmod +x $tmpdir/VentoyWeb.sh
chmod +x $tmpdir/VentoyPlugson.sh
chmod +x $tmpdir/VentoyGUI*
cp $OPT $LANG_DIR/languages.json $tmpdir/tool/
@@ -174,12 +182,14 @@ tar -czvf ventoy-${curver}-linux.tar.gz $tmpdir
rm -f ventoy-${curver}-windows.zip
cp $OPT Ventoy2Disk.exe $tmpdir/
cp $OPT VentoyPlugson.exe $tmpdir/
cp $OPT FOR_X64_ARM.txt $tmpdir/
mkdir -p $tmpdir/altexe
cp $OPT Ventoy2Disk_*.exe $tmpdir/altexe/
cp $OPT $tmpdir/tool/plugson.tar.xz $tmpdir/ventoy/
cp $OPT $LANG_DIR/languages.json $tmpdir/ventoy/
rm -rf $tmpdir/tool
rm -f $tmpdir/*.sh

View File

@@ -48,6 +48,69 @@
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
"name":"Azerbaijani (Azərbaycanca)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"Xəyyam Qocayev",
"STR_ERROR":"Xəta",
"STR_WARNING":"Xəbərdarlıq",
"STR_INFO":"Məlumat",
"STR_INCORRECT_DIR":"Lütfən, başqa kataloqda başladın!",
"STR_INCORRECT_TREE_DIR":"Lütfən məni burada başlatmayın, buraxılmış quraşdırıcı paketini endirin və başqa yerdə işə salın.",
"STR_DEVICE":"Cihaz",
"STR_LOCAL_VER":"Ventoy paketdə",
"STR_DISK_VER":"Ventoy cihazda",
"STR_STATUS":"Vəziyyəti - hazır",
"STR_INSTALL":"Quraşdırın",
"STR_UPDATE":"Yeniləyin",
"STR_UPDATE_TIP":"Yeniləmək təhlükəsizdir, ISO faylı dəyişməz qalır, #@Davam edək?",
"STR_INSTALL_TIP":"Disk formatlanacaq və ondakı bütün məlumatlkar itiriləcəkdir.#@Davam edək?",
"STR_INSTALL_TIP2":"Disk formatlanacaq və ondakı bütün məlumatlkar itiriləcəkdir.#@Həqiqətən davam etmək istəyirsiniz?",
"STR_INSTALL_SUCCESS":"Təbriklər!#@Ventoy, uğurla cihazınıza quraşdırıldı.",
"STR_INSTALL_FAILED":"Ventoyun quraşdırılması zamanı xəta baş verdi. Cihazı təkrar qoşun və yenidən cəhd edin. Daha çox məlumat almaq üçün log.txt jurnal faylına baxın.",
"STR_UPDATE_SUCCESS":"Təbriklər!#@Ventoy, uğurla cihazınıza quraşdırıldı.",
"STR_UPDATE_FAILED":"Ventoy yenilənən zaman xəta ba. verdi. Cihazı yenidən qoşun və yenidən cəhd edin. Daha ətraflı məlumat üçün log.txt jurnal faylına baxın.",
"STR_WAIT_PROCESS":"Proses başladıldı, lütfən gözləyin...",
"STR_MENU_OPTION":"Seçimlər",
"STR_MENU_SECURE_BOOT":"Secure Boot dəstəyi",
"STR_MENU_PART_CFG":"Əlavə bölmə",
"STR_BTN_OK":"ОLDU",
"STR_BTN_CANCEL":"Ləğv edin",
"STR_PRESERVE_SPACE":"Diskin sonunda əlavə bölmə yaradın",
"STR_SPACE_VAL_INVALID":"Bölmənin ölçüsündə səhv var",
"STR_MENU_CLEAR":"Ventoy'u silin",
"STR_CLEAR_SUCCESS":"Ventoy, cihazdan uğurla silindi.",
"STR_CLEAR_FAILED":"Ventoyun silinməsi zamanı xəta baş verdi. Cihazı yenidən qoşun və təkrar cəhd edin. Daha ətraflı məlumat üçün log.txt jurnal faylına baxın.",
"STR_MENU_PART_STYLE":"Diskin bölünməsi qaydası",
"STR_DISK_2TB_MBR_ERROR":"2TB-dan artıq disklər üçün GPT seçin",
"STR_SHOW_ALL_DEV":"Bütün cihazları göstərmək",
"STR_PART_ALIGN_4KB":"4KB ölçüsündəki bölməni düzləndirmək",
"STR_WEB_COMMUNICATION_ERR":"Bağlantı xətası:",
"STR_WEB_REMOTE_ABNORMAL":"Bağlantı xətası: Uzaq bağlantı aktiv deyil",
"STR_WEB_REQUEST_TIMEOUT":"Bağlantı xətası: Gözləmə vaxtı başa çatdı",
"STR_WEB_SERVICE_UNAVAILABLE":"Bağlantı xətası: Xidmət əlçatmazdır",
"STR_WEB_TOKEN_MISMATCH":"Domen vəziyyəti yeniləndi. Sonra yenidən cəhd edin.",
"STR_WEB_SERVICE_BUSY":"Xidmət mə.ğuldur, sonra cəhd edin.",
"STR_MENU_VTSI_CREATE":"VTSI faylı yaradın",
"STR_VTSI_CREATE_TIP":"Bu dəfə Ventoy, cihaza quraşdırılmayacaq, yalnız VTSI faylı yaradılacaq #@Davam edək?",
"STR_VTSI_CREATE_SUCCESS":"VTSI faylı uğurla yaradıldı!#@Ventoy'u quraşdırmağı tamamlamaq üçün həmin faylı diskə Rufus(3.15+) istifadə edərək yaza bilərsiniz.",
"STR_VTSI_CREATE_FAILED":"VTSI faylının yaradlmasında xəta.",
"STR_MENU_PART_RESIZE":"Zərər verməyən quraşdırma",
"STR_PART_RESIZE_TIP":"Ventoy mümkün olduqca zərər vermədən quraşdırmağa cəhd edir. #@Davam edək?",
"STR_PART_RESIZE_SUCCESS":"Təbriklər!#@Zərərsiz Ventoy quraşdırması başa çatdı.",
"STR_PART_RESIZE_FAILED":"Zərərsiz quraşdırma baş tutmadı, daha ətraflı öyrənmək üçün log.txt jurnal faylına baxın.",
"STR_PART_RESIZE_UNSUPPORTED":"ZƏrərsiz Ventoy quraşdırması dayandırıldı, belə ki, bəzi şərtlər yerinə yetirilə bilməd. Daha ətraflı məlumat üçün.txt jurnal faylına baxın.",
"STRXXX":""
},
{
@@ -71,9 +134,9 @@
"STR_INSTALL_TIP":"디스크가 포맷되고 모든 데이터가 손실됩니다.#@계속하시겠습니까?",
"STR_INSTALL_TIP2":"디스크가 포맷되고 모든 데이터가 손실됩니다.#@계속하시겠습니까? (다시 확인)",
"STR_INSTALL_SUCCESS":"축하합니다!#@Ventoy가 장치에 성공적으로 설치되었습니다.",
"STR_INSTALL_FAILED":"설치 중 오류가 발생했습니다. USB를 다시 연결하고 다시 시도할 수 있습니다. 자세한 내용은 log.txt를 확인하십시오.",
"STR_INSTALL_FAILED":"설치 중 오류가 발생했습니다. USB를 다시 삽입하고 다시 시도할 수 있습니다. 자세한 내용은 log.txt를 확인하십시오.",
"STR_UPDATE_SUCCESS":"축하합니다!#@Ventoy가 장치에 성공적으로 업데이트되었습니다.",
"STR_UPDATE_FAILED":"업데이트 중에 오류가 발생했습니다. USB를 다시 연결하고 다시 시도할 수 있습니다. 자세한 내용은 log.txt를 확인하십시오.",
"STR_UPDATE_FAILED":"업데이트 중에 오류가 발생했습니다. USB를 다시 삽입하고 다시 시도할 수 있습니다. 자세한 내용은 log.txt를 확인하십시오.",
"STR_WAIT_PROCESS":"현재 작업이 실행 중입니다. 기다려 주십시오...",
"STR_MENU_OPTION":"옵션",
"STR_MENU_SECURE_BOOT":"보안 부트 (Secure Boot) 지원",
@@ -84,7 +147,7 @@
"STR_SPACE_VAL_INVALID":"예약된 공간의 값이 잘못되었습니다",
"STR_MENU_CLEAR":"Ventoy 제거",
"STR_CLEAR_SUCCESS":"Ventoy가 장치에서 성공적으로 제거되었습니다.",
"STR_CLEAR_FAILED":"디스크에서 Ventoy를 지울 때 오류가 발생했습니다. USB를 다시 연결하고 다시 시도할 수 있습니다. 자세한 내용은 log.txt를 확인하십시오.",
"STR_CLEAR_FAILED":"디스크에서 Ventoy를 지울 때 오류가 발생했습니다. USB를 다시 삽입하고 다시 시도할 수 있습니다. 자세한 내용은 log.txt를 확인하십시오.",
"STR_MENU_PART_STYLE":"파티션 유형",
"STR_DISK_2TB_MBR_ERROR":"2TB 이상의 디스크는 GPT를 선택하십시오",
"STR_SHOW_ALL_DEV":"모든 장치 표시",
@@ -97,8 +160,14 @@
"STR_WEB_SERVICE_BUSY":"서비스가 사용 중입니다. 나중에 다시 시도하십시오.",
"STR_MENU_VTSI_CREATE":"VTSI 파일 생성",
"STR_VTSI_CREATE_TIP":"이번에는 장치에 쓰지 않고 VTSI 파일#@만 생성합니다.#@계속하시겠습니까?",
"STR_VTSI_CREATE_SUCCESS":"VTSI 파일이 성공적으로 생성되었습니다!#@Rufus(3.15+)를 사용하여 장치에 기록하여 Ventoy 설치를 완료할 수 있습니다.",
"STR_VTSI_CREATE_SUCCESS":"VTSI 파일이 성공적으로 생성되었습니다!#@Rufus (3.15+)를 사용하여 장치에 기록하여 Ventoy 설치를 완료할 수 있습니다.",
"STR_VTSI_CREATE_FAILED":"VTSI 파일을 생성하지 못했습니다.",
"STR_MENU_PART_RESIZE":"비파괴 설치",
"STR_PART_RESIZE_TIP":"가능하면 Ventoy가 비파괴 설치를 시도합니다. #@계속하시겠습니까?",
"STR_PART_RESIZE_SUCCESS":"축하합니다!#@Ventoy 비파괴 설치가 완료되었습니다.",
"STR_PART_RESIZE_FAILED":"비파괴 설치에 실패했습니다. 자세한 내용은 log.txt를 확인하십시오.",
"STR_PART_RESIZE_UNSUPPORTED":"일부 조건을 충족할 수 없기 때문에 Ventoy 비파괴 설치가 중지되었습니다. 자세한 내용은 log.txt를 확인하십시오.",
"STRXXX":""
},
{
@@ -150,6 +219,12 @@
"STR_VTSI_CREATE_TIP":"本操作不会向设备中写入数据,而只会生成一个 VTSI 文件#@是否继续?",
"STR_VTSI_CREATE_SUCCESS":"VTSI 文件创建成功你可以使用Rufus(3.15+)将其写入对应设备从而完成Ventoy的安装",
"STR_VTSI_CREATE_FAILED":"VTSI 文件创建失败",
"STR_MENU_PART_RESIZE":"无损安装",
"STR_PART_RESIZE_TIP":"Ventoy将尝试进行无损安装。注意任何磁盘操作都有一定的风险对于重要数据建议做好备份。#@是否继续?",
"STR_PART_RESIZE_SUCCESS":"恭喜你! Ventoy 成功完成了无损安装。",
"STR_PART_RESIZE_FAILED":"Ventoy 无损安装失败。详细信息请查阅 log.txt 文件。",
"STR_PART_RESIZE_UNSUPPORTED":"条件不满足,无法进行无损安装。详细信息请查阅 log.txt 文件。",
"STRXXX":""
},
{
@@ -201,6 +276,12 @@
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
@@ -252,6 +333,12 @@
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
@@ -299,17 +386,23 @@
"STR_WEB_SERVICE_UNAVAILABLE":"Błąd komunikacji: usługa niedostępna",
"STR_WEB_TOKEN_MISMATCH":"Stan daemona został zaktualizowany, spróbuj ponownie później.",
"STR_WEB_SERVICE_BUSY":"Usługa jest zajęta, spróbuj ponownie później.",
"STR_MENU_VTSI_CREATE":"Generate VTSI File",
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
"STR_MENU_VTSI_CREATE":"Wygeneruj plik VTSI",
"STR_VTSI_CREATE_TIP":"Tym razem nie napisze do urządzenia ale tylko wygeneruje plik VTSI#@Kontynuować?",
"STR_VTSI_CREATE_SUCCESS":"Pomyślnie wygenerowane plik VTSI!#@Możesz teraz użyć Rufus'a(3.15+) aby napisać go na urządzenie by dokończyć instlację Ventoy.",
"STR_VTSI_CREATE_FAILED":"Generacja pliku VTSI nie powiodła się.",
"STR_MENU_PART_RESIZE":"Nieniszcząsa instalacja",
"STR_PART_RESIZE_TIP":"Ventoy spróbuje nieniszczącej instalacji jeśli jest możliwa. #@Kontynuować?",
"STR_PART_RESIZE_SUCCESS":"Gratulacje!#@Nieniszcząca instlacja Ventoy zakończyła się pomyślnie.",
"STR_PART_RESIZE_FAILED":"Nieniszcząca instalacja nie powiodła się, sprawdz log.txt po szczegóły.",
"STR_PART_RESIZE_UNSUPPORTED":"Nieniszcząca instalacja Ventoy została zatrzymana ponieważ niektóre wymagania nie zostały spełnione. Sprawdz log.txt po szczegóły.",
"STRXXX":""
},
{
"name":"Portuguese Brazilian (Português do Brasil)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"EstevaoCostaG3, David BrazSan",
"Author":"EstevaoCostaG3, David BrazSan, Hildo Guillardi Júnior",
"STR_ERROR":"Erro",
"STR_WARNING":"Atenção",
@@ -350,10 +443,16 @@
"STR_WEB_SERVICE_UNAVAILABLE":"Erro de comunicação: Serviço indisponível",
"STR_WEB_TOKEN_MISMATCH":"Status daemon atualizado, por favor, tente novamente mais tarde.",
"STR_WEB_SERVICE_BUSY":"O serviço está ocupado, por favor, tente novamente mais tarde.",
"STR_MENU_VTSI_CREATE":"Generate VTSI File",
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
"STR_MENU_VTSI_CREATE":"Gerar arquivo VTSI",
"STR_VTSI_CREATE_TIP":"Não será gravado no dispositivo, desta vez, apenas derado um VTSI file#@Continuar?",
"STR_VTSI_CREATE_SUCCESS":"Arquivo VTSI criado com sucesso!#@Você pode usar Rufus(3.15+) para gravá-lo no dispositivo e completar a instalação do Ventoy.",
"STR_VTSI_CREATE_FAILED":"Criaçao do arquivo VTSI falhada.",
"STR_MENU_PART_RESIZE":"Instalação não destrutiva",
"STR_PART_RESIZE_TIP":"Ventoy tentará uma instalação não destrutiva, se possível.#@Continuar?",
"STR_PART_RESIZE_SUCCESS":"Parabéns!#@Instalação não destrutiva do Ventoy concluída com sucesso.",
"STR_PART_RESIZE_FAILED":"Falha na installação não destrutiva, cheque o arquivo log.txt para entender.",
"STR_PART_RESIZE_UNSUPPORTED":"Instalação não destrutiva do Ventoy interrompida devido fato desconhecido. Cheque o arquivo log.txt para detalhes.",
"STRXXX":""
},
{
@@ -405,6 +504,12 @@
"STR_VTSI_CREATE_TIP":"Şu an aygıta yazılmayacak,sadece bir VTSI dosyası oluşturulacak#@Devam edilsin mi?",
"STR_VTSI_CREATE_SUCCESS":"VTSI dosyası başarılı bir şekilde oluşturuldu!#@Ventoy'un aygıta kurulumunu tamamlamak için Rufus(3.15+) programını kullanabilirsiniz.",
"STR_VTSI_CREATE_FAILED":"VTSI dosyası oluşturma başarısız oldu!",
"STR_MENU_PART_RESIZE":"Tahribatsız Kurulum",
"STR_PART_RESIZE_TIP":"Ventoy,mümkünse tahribatsız kurulumu deneyecektir. . #@Devam edilsin mi?",
"STR_PART_RESIZE_SUCCESS":"Tebrikler!#@Ventoy Tahribatsız Kurulum, başarıyla tamamlandı.",
"STR_PART_RESIZE_FAILED":"Tahribatsız kurulum başarısız oldu, ayrıntılar için log.txt dosyasını kontrol edin.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy Tahribatsız Kurulum, bazı koşullar sağlanmadığı için durduruldu. Ayrıntılı bilgi için log.txt dosyasını kontrol edin.",
"STRXXX":""
},
{
@@ -452,10 +557,16 @@
"STR_WEB_SERVICE_UNAVAILABLE":"Kommunikationsfehler: Dienst nicht verfügbar",
"STR_WEB_TOKEN_MISMATCH":"Daemon-Status aktualisiert, bitte später erneut versuchen.",
"STR_WEB_SERVICE_BUSY":"Dienst ist ausgelastet, bitte später erneut versuchen.",
"STR_MENU_VTSI_CREATE":"Generate VTSI File",
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
"STR_MENU_VTSI_CREATE":"VTSI-Datei erstellen",
"STR_VTSI_CREATE_TIP":"Es wird nur eine VTSI-Datei erstellt und nichts auf ein Gerät geschrieben.#@Fortfahren?",
"STR_VTSI_CREATE_SUCCESS":"VTSI-Datei erfolgreich erstellt!#@Sie können Rufus(3.15+) zum auf das Gerät schreiben verwenden um die Installation von Ventoy fertigzustellen.",
"STR_VTSI_CREATE_FAILED":"VTSI-Datei konnte nicht erstellt werden.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy wird eine Installation ohne vorherige Formatierung versuchen. #@Fortfahren?",
"STR_PART_RESIZE_SUCCESS":"Glückwunsch!#@Die Installation von Ventoy, ohne vorherige Formatierung, wurde erfolgreich abgeschlossen.",
"STR_PART_RESIZE_FAILED":"Installation ohne vorherige Formatierung fehlgeschlagen. Für Details die log.txt prüfen.",
"STR_PART_RESIZE_UNSUPPORTED":"Installation ohne vorherige Formatierung wurde auf Grund einiger nicht erfüllbarer Bedingungen gestoppt. Für Details die log.txt prüfen.",
"STRXXX":""
},
{
@@ -507,6 +618,12 @@
"STR_VTSI_CREATE_TIP":"Aqueste còp cap descritura al disc, generacion del fichiet VTSI sonque#@Contunhar?",
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
"STR_VTSI_CREATE_FAILED":"Fracàs de la creacion del fichièr VTSI.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
@@ -558,6 +675,12 @@
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
@@ -609,6 +732,12 @@
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
@@ -660,13 +789,19 @@
"STR_VTSI_CREATE_TIP":"Esta vez no se escribirá al dispositivo, pero solo generará un archivo VTSI#@¿Continuar?",
"STR_VTSI_CREATE_SUCCESS":"¡Archivo VTSI creado exitosamente!#@Puedes usar Rufus(3.15+) para escribirlo al dispositivo a fin de completar la instalación de Ventoy.",
"STR_VTSI_CREATE_FAILED":"Fallo en el archivo VTSI creado.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
"name":"Russian (Pусский)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"BL4CKH47H4CK3R, Teraskull",
"Author":"BL4CKH47H4CK3R, Teraskull, thehugonote",
"STR_ERROR":"Ошибка",
"STR_WARNING":"Предупреждение",
@@ -681,11 +816,11 @@
"STR_UPDATE":"Обновить",
"STR_UPDATE_TIP":"Обновление безопасно, ISO-файлы останутся без изменений.#@Продолжить?",
"STR_INSTALL_TIP":"Диск будет отформатирован и все данные будут потеряны.#@Продолжить?",
"STR_INSTALL_TIP2":"Диск будет отформатирован и все данные будут потеряны.#@Вы ДЕЙСТВИТЕЛЬНО хотите продолжить?",
"STR_INSTALL_TIP2":"Диск будет отформатирован и все данные будут потеряны.#@Вы действительно хотите продолжить?",
"STR_INSTALL_SUCCESS":"Поздравляем!#@Ventoy был успешно установлен на устройство.",
"STR_INSTALL_FAILED":"Во время установки Ventoy произошла ошибка. Переподключите устройство и попробуйте снова. Проверьте log.txt на ошибки.",
"STR_INSTALL_FAILED":"Во время установки Ventoy произошла ошибка. Переподключите устройство и попробуйте снова. Проверьте файл log.txt для получения подробной информации.",
"STR_UPDATE_SUCCESS":"Поздравляем!#@Ventoy был успешно обновлен на устройстве.",
"STR_UPDATE_FAILED":"Во время обновления Ventoy произошла ошибка. Переподключите устройство и попробуйте снова. Проверьте log.txt на ошибки.",
"STR_UPDATE_FAILED":"Во время обновления Ventoy произошла ошибка. Переподключите устройство и попробуйте снова. Проверьте файл log.txt для получения подробной информации.",
"STR_WAIT_PROCESS":"Процесс запущен, пожалуйста подождите...",
"STR_MENU_OPTION":"Опции",
"STR_MENU_SECURE_BOOT":"Поддержка Secure Boot",
@@ -696,7 +831,7 @@
"STR_SPACE_VAL_INVALID":"Неверное значение размера раздела",
"STR_MENU_CLEAR":"Удалить Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy был успешно удалён с устройства.",
"STR_CLEAR_FAILED":"Во время удаления Ventoy произошла ошибка. Переподключите устройство и попробуйте снова. Проверьте log.txt на ошибки.",
"STR_CLEAR_FAILED":"Во время удаления Ventoy произошла ошибка. Переподключите устройство и попробуйте снова. Проверьте файл log.txt для получения подробной информации.",
"STR_MENU_PART_STYLE":"Стиль разметки разделов",
"STR_DISK_2TB_MBR_ERROR":"Пожалуйста, выберите GPT для дисков более 2ТБ",
"STR_SHOW_ALL_DEV":"Показать все устройства",
@@ -711,6 +846,12 @@
"STR_VTSI_CREATE_TIP":"На этот раз Ventoy не будет установлен на устройство, а будет только создан файл VTSI#@Продолжить?",
"STR_VTSI_CREATE_SUCCESS":"Файл VTSI создан успешно!#@Вы можете использовать Rufus(3.15+), чтобы записать его на устройство, для завершения установки Ventoy.",
"STR_VTSI_CREATE_FAILED":"Ошибка создания файла VTSI.",
"STR_MENU_PART_RESIZE":"Неразрушающая установка",
"STR_PART_RESIZE_TIP":"Ventoy попробует неразрушающую установку, если это возможно. #@Продолжить?",
"STR_PART_RESIZE_SUCCESS":"Поздравляем!#@Неразрушающая установка Ventoy успешно завершена.",
"STR_PART_RESIZE_FAILED":"Не удалось выполнить неразрушающую установку, проверьте файл log.txt для получения подробной информации.",
"STR_PART_RESIZE_UNSUPPORTED":"Неразрушающая установка Ventoy остановлена, поскольку некоторые условия не могут быть выполнены. Проверьте файл log.txt для получения подробной информации.",
"STRXXX":""
},
{
@@ -762,6 +903,12 @@
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
@@ -813,13 +960,19 @@
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
"name":"Dutch (Nederlands)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"UmitCanbolat",
"Author":"UmitCanbolat, RockyTDR",
"STR_ERROR":"Fout",
"STR_WARNING":"Waarschuwing",
@@ -864,6 +1017,12 @@
"STR_VTSI_CREATE_TIP":"Deze keer wordt er niet naar het apparaat geschreven, maar wordt er alleen een VTSI-bestand gegenereerd#@Doorgaan?",
"STR_VTSI_CREATE_SUCCESS":"VTSI-bestand met succes aangemaakt!#@U kunt Rufus(3.15+) gebruiken om het bestand naar het apparaat te schrijven om de installatie van Ventoy te voltooien.",
"STR_VTSI_CREATE_FAILED":"Aanmaken van VTSI-bestand mislukt.",
"STR_MENU_PART_RESIZE":"Niet-destructieve installatie",
"STR_PART_RESIZE_TIP":"Ventoy zal indien mogelijk een niet-destructieve installatie proberen. #@Doorgaan?",
"STR_PART_RESIZE_SUCCESS":"Gefeliciteerd!#@De niet-destructieve installatie van Ventoy is met succes voltooid.",
"STR_PART_RESIZE_FAILED":"Niet-destructieve installatie mislukt. Controleer log.txt voor details.",
"STR_PART_RESIZE_UNSUPPORTED":"De niet-destructieve installatie van Ventoy is gestopt omdat aan sommige voorwaarden niet kan worden voldaan. Controleer log.txt voor details.",
"STRXXX":""
},
{
@@ -915,19 +1074,25 @@
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
"name":"Japanese (日本語)",
"FontFamily":"Yu Gothic UI",
"FontSize":14,
"Author":"taichi eto,Bentnand",
"Author":"taichi eto, Bentnand, cmplstofB",
"STR_ERROR":"エラー",
"STR_WARNING":"警告",
"STR_INFO":"情報",
"STR_INCORRECT_DIR":"正しいディレクトリーで実行してください",
"STR_INCORRECT_TREE_DIR":"こで実行するには、パッケージを導入してください。",
"STR_INCORRECT_TREE_DIR":"この場所で実行するには、パッケージを導入してください。",
"STR_DEVICE":"機器",
"STR_LOCAL_VER":"パッケージ中のVentoy",
"STR_DISK_VER":"機器中のVentoy",
@@ -937,9 +1102,9 @@
"STR_UPDATE_TIP":"更新可能です、ISOファイルは改変されません。#@続行しますか?",
"STR_INSTALL_TIP":"選択した機器は完全に初期化され、保存されたデータは二度と復元できません。#@続行しますか?",
"STR_INSTALL_TIP2":"選択した機器は完全に初期化され、保存されたデータは二度と復元できません。#@続行しますか?(再確認)",
"STR_INSTALL_SUCCESS":"おめでとうございます。#@Ventoy は正常に導入されました。",
"STR_INSTALL_FAILED":"導入中にエラーが発生しました。機器を再接続してもう一度やり直してください。 詳細な記録は log.txt にあります。",
"STR_UPDATE_SUCCESS":"おめでとうございます。#@Ventoy は正常に更新されました。",
"STR_INSTALL_SUCCESS":"おめでとうございます。#@Ventoyの導入は正常に行われました。",
"STR_INSTALL_FAILED":"導入中にエラーが発生しました。機器を再接続してもう一度やり直してください。詳細な記録は log.txt にあります。",
"STR_UPDATE_SUCCESS":"おめでとうございます。#@Ventoyの更新は正常に行われました。",
"STR_UPDATE_FAILED":"更新中にエラーが発生しました。機器を再接続してもう一度やり直してください。詳細な記録は log.txt にあります。",
"STR_WAIT_PROCESS":"スレッドが稼動しています。お待ちください...",
"STR_MENU_OPTION":"設定",
@@ -966,57 +1131,69 @@
"STR_VTSI_CREATE_TIP":"VTSIファイルを生成し記憶装置への書き込みは行いません。#@続行しますか?",
"STR_VTSI_CREATE_SUCCESS":"VTSIファイルが生成されました。#@Rufus3.15以上の版を使って記憶装置に書き込んでVentoyの導入を完遂しましょう。",
"STR_VTSI_CREATE_FAILED":"VTSIファイルを生成できませんでした。",
"STR_MENU_PART_RESIZE":"非破壊的導入",
"STR_PART_RESIZE_TIP":"Ventoyを可能であれば非破壊的に導入します。#@続行しますか?",
"STR_PART_RESIZE_SUCCESS":"おめでとうございます。#@Ventoyの非破壊的導入は正常に行われました。",
"STR_PART_RESIZE_FAILED":"Ventoyを非破壊的に導入できませんでした。詳細な記録は log.txt にあります。",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoyを非破壊的に導入できませんでした。非破壊的導入にあたっての要件が満たされていません。詳細な記録は log.txt にあります。",
"STRXXX":""
},
{
"name":"Italian (Italiano)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"AverageUser2,Albano Battistella",
"Author":"AverageUser2,Albano Battistella,bovirus",
"STR_ERROR":"Errore",
"STR_WARNING":"Attenzione",
"STR_INFO":"Info",
"STR_INCORRECT_DIR":"Si prega di eseguire nella cartella corretta",
"STR_INCORRECT_TREE_DIR":"Non eseguire qui, scarica il pacchetto di installazione ed avvialo",
"STR_INCORRECT_DIR":"Eseguilo nella cartella corretta",
"STR_INCORRECT_TREE_DIR":"Non eseguirlo qui.#@Scarica il pacchetto di installazione ed avvialo.",
"STR_DEVICE":"Dispositivo",
"STR_LOCAL_VER":"Versione locale di Ventoy",
"STR_DISK_VER":"Ventoy nel dispositivo",
"STR_STATUS":"Stato - PRONTO",
"STR_INSTALL":"Installa",
"STR_UPDATE":"Aggiorna",
"STR_UPDATE_TIP":"L'aggiornamento è sicuro, i file presenti nel dispositivo rimarranno invariati.#@Continuare?",
"STR_INSTALL_TIP":"Il disco verrà formattato e tutti i dati saranno persi.#@Continuare?",
"STR_INSTALL_TIP2":"Il disco verrà formattato e tutti i dati saranno persi.#@Continuare?' (seconda verifica)",
"STR_INSTALL_SUCCESS":"Congratulazioni!#@Ventoy è stato installato con successo nel dispositivo",
"STR_INSTALL_FAILED":"Si è verificato un errore durante l'installazione. Riconnetti il dispostivo e riprova. Controlla il file log.txt per i dettagli.",
"STR_UPDATE_SUCCESS":"Congratulazioni!#@Ventoy è stato aggiornato con successo nel dispositivo",
"STR_UPDATE_FAILED":"Si è verificato un errore durante l'aggiornamento. Riconnetti il dispostivo e riprova. Controlla il file log.txt per i dettagli.",
"STR_WAIT_PROCESS":"Un processo è in esecuzione, attendere prego...",
"STR_UPDATE_TIP":"L'aggiornamento è sicuro, i file presenti nel dispositivo rimarranno invariati.#@Vuoi continuare?",
"STR_INSTALL_TIP":"Il disco verrà formattato e tutti i dati saranno persi.#@Vuoi continuare?",
"STR_INSTALL_TIP2":"Il disco verrà formattato e tutti i dati saranno persi.#@Vuoi continuare (seconda verifica)?",
"STR_INSTALL_SUCCESS":"Congratulazioni!#@Installazione di Ventoy nel dispositivo completata.",
"STR_INSTALL_FAILED":"Si è verificato un errore durante l'installazione.#@Riconnetti il dispositivo e riprova.#@Per i dettagli controlla il file log.txt .",
"STR_UPDATE_SUCCESS":"Congratulazioni!#@Aggiornamento di Ventoy nel dispositivo completato",
"STR_UPDATE_FAILED":"Si è verificato un errore durante l'aggiornamento.#@Riconnetti il dispositivo e riprova.#@Per i dettagli controlla il file log.txt.",
"STR_WAIT_PROCESS":"Un processo è in esecuzione. Attendi...",
"STR_MENU_OPTION":"Opzioni",
"STR_MENU_SECURE_BOOT":"Avvio protetto (secure boot)",
"STR_MENU_PART_CFG":"Configurazione della partizione",
"STR_MENU_PART_CFG":"Configurazione partizione",
"STR_BTN_OK":"OK",
"STR_BTN_CANCEL":"Annulla",
"STR_PRESERVE_SPACE":"Riserva spazio nella parte finale del disco",
"STR_SPACE_VAL_INVALID":"Quantità di spazio da riservare non valida",
"STR_MENU_CLEAR":"Rimuovi Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy è stato rimosso con successo dal dispositivo.",
"STR_CLEAR_FAILED":"Si è verificato un errore durante la rimozione di Ventoy dal dispositivo. Riconnetti il dispositivo e riprova. Controlla il file log.txt per maggiori dettagli",
"STR_MENU_PART_STYLE":"Stile Tabella delle partizioni",
"STR_CLEAR_SUCCESS":"Rimozione di Ventoy dal dispositivo completata.",
"STR_CLEAR_FAILED":"Si è verificato un errore durante la rimozione di Ventoy dal dispositivo.#@Riconnetti il dispositivo e riprova.#@Per i dettagli controlla il file log.txt.",
"STR_MENU_PART_STYLE":"Stile tabella partizioni",
"STR_DISK_2TB_MBR_ERROR":"Seleziona GPT per dischi con dimensioni maggiori di 2TB",
"STR_SHOW_ALL_DEV":"Mostra tutti i dispositivi",
"STR_SHOW_ALL_DEV":"Visualizza tutti i dispositivi",
"STR_PART_ALIGN_4KB":"Allinea le partizioni con 4KB",
"STR_WEB_COMMUNICATION_ERR":"Errore di comunicazione:",
"STR_WEB_REMOTE_ABNORMAL":"Errore di comunicazione: remoto anormale",
"STR_WEB_REQUEST_TIMEOUT":"Errore di comunicazione: richiesta scaduta",
"STR_WEB_SERVICE_UNAVAILABLE":"Errore di comunicazione: servizio non disponibile",
"STR_WEB_TOKEN_MISMATCH":"Stato del demone aggiornato, riprova più tardi.",
"STR_WEB_SERVICE_BUSY":"Il servizio è occupato, riprova più tardi.",
"STR_WEB_TOKEN_MISMATCH":"Stato del demone aggiornato. Riprova più tardi.",
"STR_WEB_SERVICE_BUSY":"Il servizio è occupato. Riprova più tardi.",
"STR_MENU_VTSI_CREATE":"Genera file VTSI",
"STR_VTSI_CREATE_TIP":"Questa volta non scriverà sul dispositivo, ma genererà solo un file VTSI#@Continuare?",
"STR_VTSI_CREATE_SUCCESS":"File VTSI creato con successo!#@Puoi usare Rufus (versione 3.15 o successiva) per scrivere sul dispositivo in modo da completare l'installazione di Ventoy.",
"STR_VTSI_CREATE_FAILED":"Creazione File VTSI non riuscito.",
"STR_VTSI_CREATE_TIP":"Questa volta non scriverà sul dispositivo, ma genererà solo un file VTSI#@Vuoi continuare?",
"STR_VTSI_CREATE_SUCCESS":"Creazione file VTSI completata!#@Per scrivere nel dispositivo in modo da completare l'installazione di Ventoy puoi usare Rufus (versione 3.15 o successiva).",
"STR_VTSI_CREATE_FAILED":"Creazione file VTSI non riuscita.",
"STR_MENU_PART_RESIZE":"Installazione non distruttiva",
"STR_PART_RESIZE_TIP":"Ventoy proverà, se possibile, l'installazione non distruttiva.#@Vuoi continuare?",
"STR_PART_RESIZE_SUCCESS":"Congratulazioni!#@Installazione non distruttiva di Ventoy completata.",
"STR_PART_RESIZE_FAILED":"Installazione non distruttiva fallita.#@Per i dettagli controlla il file log.txt.",
"STR_PART_RESIZE_UNSUPPORTED":"L'installazione non distruttiva di Ventoy è stata interrotta perché alcune condizioni non possono essere soddisfatte.#@Per i dettagli controlla il file log.txt.",
"STRXXX":""
},
{
@@ -1068,6 +1245,12 @@
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
@@ -1119,13 +1302,19 @@
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
"name":"Chinese Traditional (繁體中文)",
"name":"Traditional Chinese體中文",
"FontFamily":"新細明體",
"FontSize":14,
"Author":"penut85420",
"Author":"penut85420,tony8077616",
"STR_ERROR":"錯誤",
"STR_WARNING":"警告",
@@ -1133,43 +1322,49 @@
"STR_INCORRECT_DIR":"請在正確的資料夾下開啟!",
"STR_INCORRECT_TREE_DIR":"請下載並使用發行版本的安裝包",
"STR_DEVICE":"裝置",
"STR_LOCAL_VER":"當前 Ventoy 版本",
"STR_DISK_VER":"裝置內部的 Ventoy 版本",
"STR_LOCAL_VER":"安裝包內 Ventoy 版本",
"STR_DISK_VER":"裝置內 Ventoy 版本",
"STR_STATUS":"狀態 - 準備就緒",
"STR_INSTALL":"安裝",
"STR_UPDATE":"升級",
"STR_UPDATE_TIP":"升級操作是安全的,磁碟內的 ISO 文件不會被清除#@是否繼續?",
"STR_INSTALL_TIP":"磁碟將會被格式化,所有內容將會被清除!#@是否繼續?",
"STR_INSTALL_TIP2":"磁碟將會被格式化,所有內容將會被清除!#@再次確認是否繼續?",
"STR_UPDATE_TIP":"升級操作是安全的,磁碟內的 ISO 檔案不會被清除#@請問是否繼續?",
"STR_INSTALL_TIP":"磁碟將會被格式化,所有內容將會被清除!#@請問是否繼續?",
"STR_INSTALL_TIP2":"磁碟將會被格式化,所有內容將會被清除!#@再次確認是否繼續?",
"STR_INSTALL_SUCCESS":"恭喜Ventoy 已經成功安裝到此裝置中!",
"STR_INSTALL_FAILED":"安裝 Ventoy 的過程中發生錯誤,請重新插入磁碟重試一次,詳細訊息請調閱 log.txt 文件。",
"STR_INSTALL_FAILED":"安裝 Ventoy 的過程中發生錯誤,請再次重新插入磁碟重試,詳細訊息請檢視 log.txt 檔案。",
"STR_UPDATE_SUCCESS":"恭喜,新版本的 Ventoy 已經成功更新到此裝置中!",
"STR_UPDATE_FAILED":"更新 Ventoy 的過程中發生錯誤,請重新插入磁碟重試一次,詳細訊息請調閱 log.txt 文件。",
"STR_WAIT_PROCESS":"目前有執行緒正在運作中,請稍候",
"STR_UPDATE_FAILED":"更新 Ventoy 的過程中發生錯誤,請再次重新插入磁碟重試,詳細訊息請檢視 log.txt 檔案。",
"STR_WAIT_PROCESS":"目前有執行緒正在運作中,請稍候...",
"STR_MENU_OPTION":"選項",
"STR_MENU_SECURE_BOOT":"支援 Secure Boot",
"STR_MENU_PART_CFG":"分區配置",
"STR_MENU_SECURE_BOOT":"支援安全開機",
"STR_MENU_PART_CFG":"分區配置",
"STR_BTN_OK":"確定",
"STR_BTN_CANCEL":"取消",
"STR_PRESERVE_SPACE":"在磁最後保留一部分空間",
"STR_SPACE_VAL_INVALID":"保留空間的大小不合法",
"STR_MENU_CLEAR":"清除Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy已成功從設備中清除",
"STR_CLEAR_FAILED":"清除 Ventoy 的過程中發生錯誤,請重新插入磁碟重試一次,詳細訊息請調閱 log.txt 文件。",
"STR_MENU_PART_STYLE":"分格式",
"STR_DISK_2TB_MBR_ERROR":"對於超過2TB的磁請選擇GPT分區格式",
"STR_SHOW_ALL_DEV":"顯示所有設備",
"STR_PART_ALIGN_4KB":"區按照4KB對齊",
"STR_WEB_COMMUNICATION_ERR":"通錯誤:",
"STR_WEB_REMOTE_ABNORMAL":"通錯誤: 服務端異常",
"STR_WEB_REQUEST_TIMEOUT":"通錯誤: 請求時",
"STR_WEB_SERVICE_UNAVAILABLE":"通錯誤: 服務不可用",
"STR_WEB_TOKEN_MISMATCH":"服務狀態已更新",
"STR_WEB_SERVICE_BUSY":"服務正忙,請稍後試",
"STR_MENU_VTSI_CREATE":"Generate VTSI File",
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
"STR_PRESERVE_SPACE":"在磁最後保留一部分空間",
"STR_SPACE_VAL_INVALID":"保留空間的容量不正確",
"STR_MENU_CLEAR":"清除 Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy 已成功從裝置中清除",
"STR_CLEAR_FAILED":"清除 Ventoy 的過程中發生錯誤,請再次重新插入磁碟重試,詳細訊息請檢視 log.txt 檔案。",
"STR_MENU_PART_STYLE":"分割表格式",
"STR_DISK_2TB_MBR_ERROR":"超過 2TB 的磁請選擇 GPT 分割表格式",
"STR_SHOW_ALL_DEV":"顯示所有裝置",
"STR_PART_ALIGN_4KB":"磁碟分割區按照 4KB 對齊",
"STR_WEB_COMMUNICATION_ERR":"通錯誤:",
"STR_WEB_REMOTE_ABNORMAL":"通錯誤: 伺服器端發生異常",
"STR_WEB_REQUEST_TIMEOUT":"通錯誤: 請求時",
"STR_WEB_SERVICE_UNAVAILABLE":"通錯誤: 伺服器無法使用",
"STR_WEB_TOKEN_MISMATCH":"伺服器狀態已更新",
"STR_WEB_SERVICE_BUSY":"伺服器忙碌中,請稍後試",
"STR_MENU_VTSI_CREATE":"建立 VTSI 檔案",
"STR_VTSI_CREATE_TIP":"這個操作將只會在原地目錄建立一個 VTSI 的檔案#@請問是否繼續?",
"STR_VTSI_CREATE_SUCCESS":"VTSI 檔案建立完成!#@您可以使用 Rufus(3.15+) 將 VTSI 檔案寫入指定的裝置以完成 Ventoy 的安裝。",
"STR_VTSI_CREATE_FAILED":"VTSI 檔案建立失敗。",
"STR_MENU_PART_RESIZE":"無損安裝",
"STR_PART_RESIZE_TIP":"Ventoy 將嘗試進行無損安裝。#@請注意:任何對於磁碟的任何操作都存在一定的風險,對於重要的資料建議您做好備份!#@請問您是否繼續?",
"STR_PART_RESIZE_SUCCESS":"恭喜!#@Ventoy 已完成無損安裝。",
"STR_PART_RESIZE_FAILED":"Ventoy 無損安裝失敗。詳細訊息請檢視 log.txt 檔案。",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy 無損安裝已中止因為未滿足部分條件。詳細訊息請檢視 log.txt 檔案。",
"STRXXX":""
},
{
@@ -1221,6 +1416,12 @@
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
@@ -1272,6 +1473,12 @@
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
@@ -1323,6 +1530,12 @@
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
@@ -1374,6 +1587,12 @@
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
@@ -1396,9 +1615,9 @@
"STR_UPDATE_TIP":"Việc cập nhật Ventoy là an toàn, các tập tin ISO của bạn sẽ được giữ nguyên trạng.#@Bạn thật sự muốn tiếp tục?",
"STR_INSTALL_TIP":"Thiết bị sẽ được định dạng và do đó TẤT CẢ DỮ LIỆU trên thiết bị sẽ bị mất.#@Bạn thật sự muốn tiếp tục?",
"STR_INSTALL_TIP2":"Thiết bị sẽ được định dạng và do đó TẤT CẢ DỮ LIỆU trên thiết bị sẽ bị mất.#@Bạn thật sự muốn tiếp tục? (Xác nhận lần hai)",
"STR_INSTALL_SUCCESS":"Chúc mừng bạn !.#@Thiết bị đã được cài Ventoy thành công.",
"STR_INSTALL_SUCCESS":"Chúc mừng bạn!#@Thiết bị đã được cài Ventoy thành công.",
"STR_INSTALL_FAILED":"Đã xảy ra lỗi trong quá trình cài đặt Ventoy. Bạn có thể rút thiết bị ra và thử lại. Xem chi tiết ở tệp log.txt.",
"STR_UPDATE_SUCCESS":"Chúc mừng bạn !.#@Thiết bị đã được cập nhật Ventoy thành công.",
"STR_UPDATE_SUCCESS":"Chúc mừng bạn!#@Thiết bị đã được cập nhật Ventoy thành công.",
"STR_UPDATE_FAILED":"Đã xảy ra lỗi trong quá trình cập nhật Ventoy. Bạn có thể rút thiết bị ra và thử lại. Xem chi tiết ở tệp log.txt.",
"STR_WAIT_PROCESS":"Một luồng xử lý đang chạy, vui lòng chờ...",
"STR_MENU_OPTION":"Tùy chọn",
@@ -1409,7 +1628,7 @@
"STR_PRESERVE_SPACE":"Giữ lại phần dung lượng ở cuối thiết bị",
"STR_SPACE_VAL_INVALID":"Giá trị dung lượng giữ lại không hợp lệ.",
"STR_MENU_CLEAR":"Gỡ bỏ Ventoy",
"STR_CLEAR_SUCCESS":"Chúc mừng bạn !.#@Thiết bị đã được gỡ bỏ Ventoy thành công.",
"STR_CLEAR_SUCCESS":"Chúc mừng bạn!#@Thiết bị đã được gỡ bỏ Ventoy thành công.",
"STR_CLEAR_FAILED":"Đã xảy ra lỗi trong quá trình gỡ bỏ Ventoy. Bạn có thể rút thiết bị ra và thử lại. Xem chi tiết ở tệp log.txt.",
"STR_MENU_PART_STYLE":"Kiểu phân vùng",
"STR_DISK_2TB_MBR_ERROR":"Thiết bị có dung lượng lớn hơn 2TB. Vui lòng chọn Kiểu phân vùng là GPT.",
@@ -1421,10 +1640,15 @@
"STR_WEB_SERVICE_UNAVAILABLE":"Lỗi giao tiếp: Dịch vụ không sẵn có",
"STR_WEB_TOKEN_MISMATCH":"Đã cập nhật trạng thái Daemon, vui lòng thử lại sau.",
"STR_WEB_SERVICE_BUSY":"Dịch vụ bận, vui lòng thử lại sau.",
"STR_MENU_VTSI_CREATE":"Tạo tệp VTSI",
"STR_MENU_VTSI_CREATE":"Tạo tệp VTSI",
"STR_VTSI_CREATE_TIP":"Lần này sẽ không ghi vào thiết bị, chỉ tạo một tệp VTSI#@Bạn muốn tiếp tục?",
"STR_VTSI_CREATE_SUCCESS":"Tạo tệp VTSI thành công!#@Để hoàn thành cài đặt Ventoy, bạn có thể dùng Rufus (3.15+) để ghi tệp này vào thiết bị.",
"STR_VTSI_CREATE_FAILED":"Tạo tệp VTSI đã gặp lỗi.",
"STR_MENU_PART_RESIZE":"Cài đặt không phá hủy",
"STR_PART_RESIZE_TIP":"Ventoy sẽ thử cài đặt không phá hủy nếu có thể. #@Bạn muốn tiếp tục?",
"STR_PART_RESIZE_SUCCESS":"Chúc mừng bạn!#@Thiết bị đã được cài Ventoy thành công theo cách cài đặt không phá hủy.",
"STR_PART_RESIZE_FAILED":"Đã xảy ra lỗi trong quá trình cài Ventoy theo cách cài đặt không phá hủy. Xem chi tiết ở tệp log.txt.",
"STR_PART_RESIZE_UNSUPPORTED":"Cài Ventoy theo cách cài đặt không phá hủy đã bị dừng lại vì chưa đúng điều kiện. Xem chi tiết ở tệp log.txt.",
"STRXXX":""
},
{
@@ -1476,6 +1700,12 @@
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
@@ -1527,6 +1757,12 @@
"STR_VTSI_CREATE_TIP":"Овој пат ништо нема да се запише на уредот туку само ќе се генерира VTSI датотека#@Продолжи?",
"STR_VTSI_CREATE_SUCCESS":"Успешно креирана VTSI датотека!#@Можете да го користите Rufus(3.15+) за да ја запишете на уредот како и да ја комплетирате инсталацијата на Ventoy.",
"STR_VTSI_CREATE_FAILED":"Креирањето на VTSI датотека е неуспешно.",
"STR_MENU_PART_RESIZE":"Недеструктивна инсталација",
"STR_PART_RESIZE_TIP":"Ventoy ќе се обиде со недеструктивна инсталација доколку е возможно. #@Продолжи?",
"STR_PART_RESIZE_SUCCESS":"Честитки! Недеструктивната инсталација е успешно завршена.",
"STR_PART_RESIZE_FAILED":"Недеструктивната инсталација не успеа. Проверете го log.txt за детали.",
"STR_PART_RESIZE_UNSUPPORTED":"Недеструктивната инсталација на Ventoy е запрена бидејќи некои услови не се исполнети. Проверете го log.txt за детали.",
"STRXXX":""
},
{
@@ -1578,6 +1814,12 @@
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
@@ -1629,11 +1871,17 @@
"STR_VTSI_CREATE_TIP":"Desta vez não irá gravar no dispositivo, mas apenas gerar um ficheiro VTSI#@Continuar?",
"STR_VTSI_CREATE_SUCCESS":"Ficheiro VTSI criado com sucesso!#@Pode utilizar o Rufus(3.15+) para o gravar no dispositivo de modo a completar a instalação do Ventoy.",
"STR_VTSI_CREATE_FAILED":"Falha no ficheiro VTSI criado.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
"name":"Indonesian (Bahasa Indonesia)",
"FontFamily":"Comic Sans MS",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"Ida Bagus Anom Sanjaya",
@@ -1661,25 +1909,31 @@
"STR_MENU_PART_CFG":"Konfigurasi Partisi",
"STR_BTN_OK":"OK",
"STR_BTN_CANCEL":"Batal",
"STR_PRESERVE_SPACE":"Mempertahankan sejumlah ruang penyimpanan pada disk di bawah ini",
"STR_SPACE_VAL_INVALID":"Nilai menpertahankan ruang tidak valid",
"STR_PRESERVE_SPACE":"Menyisakan sejumlah ruang penyimpanan pada disk di bawah ini",
"STR_SPACE_VAL_INVALID":"Nilai penyisaan ruang tidak valid",
"STR_MENU_CLEAR":"Bersihkan Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy telah berhasil dihapus pada perangkat ini.",
"STR_CLEAR_FAILED":"Terjadi kesalahan ketika penghapusan berlangsung. Anda perlu mencabut-pasang ulang USB dan coba lagi. Cek log.txt untuk detil.",
"STR_CLEAR_FAILED":"Terjadi kesalahan ketika penghapusan berlangsung. Anda perlu mencabut-pasang ulang USB dan coba lagi. Periksa berkas log.txt untuk detil.",
"STR_MENU_PART_STYLE":"Gaya Partisi",
"STR_DISK_2TB_MBR_ERROR":"Silakan pilih GPT untuk disk yang lebih dari 2TB",
"STR_SHOW_ALL_DEV":"Tampilkan semua perangkat",
"STR_PART_ALIGN_4KB":"Meluruskan dengan partisi 4KB",
"STR_WEB_COMMUNICATION_ERR":"Kesalahan komunikasi:",
"STR_WEB_REMOTE_ABNORMAL":"Kesalahan komunikasi: tidak normalnya kendali",
"STR_WEB_REMOTE_ABNORMAL":"Kesalahan komunikasi: pengendali bermasalah",
"STR_WEB_REQUEST_TIMEOUT":"Kesalahan komunikasi: Waktu permintaan habis",
"STR_WEB_SERVICE_UNAVAILABLE":"Kesalahan komunikasi: Layanan tidak tersedia",
"STR_WEB_TOKEN_MISMATCH":"Status daemon diperbarui, silakan coba lagi nanti.",
"STR_WEB_SERVICE_BUSY":"Layanan sedang sibuk, silakan coba lagi nanti.",
"STR_MENU_VTSI_CREATE":"Membuat berkas VTSI",
"STR_VTSI_CREATE_TIP":"Saat ini tidak akan menuliskan di perangkat, tetapi hanya membuat berkas VTSI #@Lanjutkan?",
"STR_VTSI_CREATE_SUCCESS":"Berkas VTSI berhasil dibuat#@Anda bisa menggunakan Rufus(3.15+) untuk menulisnya ke perangkat untuk menyelesaikan instalasi Ventoy.",
"STR_VTSI_CREATE_SUCCESS":"Berkas VTSI berhasil dibuat#@Anda bisa menggunakan Rufus(3.15+) untuk menulisnya ke perangkat untuk menyelesaikan pemasangan Ventoy.",
"STR_VTSI_CREATE_FAILED":"Berkas VTSI gagal dibuat.",
"STR_MENU_PART_RESIZE":"Pemasangan tanpa merusakkan",
"STR_PART_RESIZE_TIP":"Ventoy akan mencoba pemasangan tanpa merusakkan apabila memungkinkan. #@Lanjutkan?",
"STR_PART_RESIZE_SUCCESS":"Selamat!#@Pemasangan tanpa merusakkan Ventoy berhasil.",
"STR_PART_RESIZE_FAILED":"Pemasangan tanpa merusakkan gagal, periksa berkas log.txt untuk detil.",
"STR_PART_RESIZE_UNSUPPORTED":"Pemasangan tanpa merusakkan Ventoy terhenti karena beberapa kondisi yang tidak mendukung. Periksa berkas log.txt untuk detil.",
"STRXXX":""
},
{
@@ -1731,13 +1985,19 @@
"STR_VTSI_CREATE_TIP":"Dette vil ikke skrive til enheten, men kun generere en VTSIfil#@Fortsett?",
"STR_VTSI_CREATE_SUCCESS":"VTSI-fil opprettet.#@Du kan bruke Rufus(3.15+) til å skrive den til enheten for å fullføre installasjonen av Ventoy.",
"STR_VTSI_CREATE_FAILED":"Noe gikk galt under opprettelse av VTSI-fil.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
"name":"Ukrainian (Українська)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"Teraskull",
"Author":"Teraskull, thehugonote",
"STR_ERROR":"Помилка",
"STR_WARNING":"Попередження",
@@ -1752,11 +2012,11 @@
"STR_UPDATE":"Оновити",
"STR_UPDATE_TIP":"Процес оновлення безпечний, файли ISO залишаться незмінними.#@Продовжити?",
"STR_INSTALL_TIP":"Диск буде відформатовано, і всі дані будуть втрачені.#@Продовжити?",
"STR_INSTALL_TIP2":"Диск буде відформатовано, і всі дані будуть втрачені.#@Продовжити? (Подвійна перевірка)",
"STR_INSTALL_TIP2":"Диск буде відформатовано, і всі дані будуть втрачені.#@Ви дійсно хочете продовжити?",
"STR_INSTALL_SUCCESS":"Вітаємо!#@Ventoy успішно встановлено на пристрій.",
"STR_INSTALL_FAILED":"Під час встановлення сталася помилка. Ви можете ще раз підключити USB і повторити спробу. Перевірте log.txt для деталей.",
"STR_INSTALL_FAILED":"Під час встановлення сталася помилка. Ви можете ще раз підключити USB і повторити спробу. Перевірте log.txt для отримання детальної інформації.",
"STR_UPDATE_SUCCESS":"Вітаємо!#@Ventoy на пристрої успішно оновлено.",
"STR_UPDATE_FAILED":"Під час оновлення сталася помилка. Ви можете ще раз підключити USB і повторити спробу. Перевірте log.txt для деталей.",
"STR_UPDATE_FAILED":"Під час оновлення сталася помилка. Ви можете ще раз підключити USB і повторити спробу. Перевірте log.txt для отримання детальної інформації.",
"STR_WAIT_PROCESS":"Потік запущено, зачекайте...",
"STR_MENU_OPTION":"Опції",
"STR_MENU_SECURE_BOOT":"Підтримка Secure Boot",
@@ -1767,7 +2027,7 @@
"STR_SPACE_VAL_INVALID":"Недійсне значення для зарезервованого простору",
"STR_MENU_CLEAR":"Видалити Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy успішно видалено з пристрою.",
"STR_CLEAR_FAILED":"Під час видалення Ventoy сталася помилка. Ви можете ще раз підключити USB і повторити спробу. Перевірте log.txt для деталей.",
"STR_CLEAR_FAILED":"Під час видалення Ventoy сталася помилка. Ви можете ще раз підключити USB і повторити спробу. Перевірте log.txt для отримання детальної інформації.",
"STR_MENU_PART_STYLE":"Стиль розмітки розділів",
"STR_DISK_2TB_MBR_ERROR":"Будь ласка, виберіть GPT для дисків понад 2TB",
"STR_SHOW_ALL_DEV":"Показати всі пристрої",
@@ -1782,6 +2042,12 @@
"STR_VTSI_CREATE_TIP":"Цього разу Ventoy не буде встановлено на пристрій, а лише буде створено файл VTSI#@Продовжити?",
"STR_VTSI_CREATE_SUCCESS":"Файл VTSI створено успішно!#@Ви можете використати Rufus(3.15+), щоб записати його на пристрій, для завершення встановлення Ventoy",
"STR_VTSI_CREATE_FAILED":"Не вдалося створити файл VTSI.",
"STR_MENU_PART_RESIZE":"Неруйнівна установка",
"STR_PART_RESIZE_TIP":"Ventoy спробує виконати неруйнівну установку, якщо це можливо. #@Продовжити?",
"STR_PART_RESIZE_SUCCESS":"Вітаємо!#@Неруйнівна установка Ventoy успішно завершена.",
"STR_PART_RESIZE_FAILED":"Збій неруйнівної установки, перевірте log.txt для отримання детальної інформації.",
"STR_PART_RESIZE_UNSUPPORTED":"Неруйнівна установка Ventoy зупинена через неможливість виконання деяких умов. Перевірте log.txt для отримання детальної інформації.",
"STRXXX":""
},
{
@@ -1833,6 +2099,12 @@
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
@@ -1884,6 +2156,12 @@
"STR_VTSI_CREATE_TIP":"Den här gången skrivs det inget till enheten, utan det skapas endast en VTSI-fil#@Fortsätta?",
"STR_VTSI_CREATE_SUCCESS":"VTSI-filen skapad!#@Använd Rufus (3.15+) till att skriva till enheten för att slutföra installationen av Ventoy.",
"STR_VTSI_CREATE_FAILED":"Misslyckades med att skapa VTSI-filen.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
@@ -1935,6 +2213,12 @@
"STR_VTSI_CREATE_TIP":"This time will not write to the device, but only generate a VTSI file#@Continue?",
"STR_VTSI_CREATE_SUCCESS":"VTSI file created successfully!#@You can use Rufus(3.15+) to write it to the device so as to complete the installation of Ventoy.",
"STR_VTSI_CREATE_FAILED":"VTSI file created failed.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
@@ -1986,6 +2270,12 @@
"STR_VTSI_CREATE_TIP":"Сега няма да се записва на диска, само ще се генерира VTSI файл#@Продължаваме?",
"STR_VTSI_CREATE_SUCCESS":"VTSI файла бе създаден успешно!#@Може да използвате Rufus(3.15+) да го запишете на устройството за инсталацията с Ventoy.",
"STR_VTSI_CREATE_FAILED":"VTSI файла създаване се провали.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
@@ -2037,6 +2327,12 @@
"STR_VTSI_CREATE_TIP":"Այս անգամ չի գրվի կրիչի վրա, այլ միայն կստեղծվի VTSI ֆայլ#@Շարունակել?",
"STR_VTSI_CREATE_SUCCESS":"VTSI ֆայլը հաջողությամբ ստեղծվեց!#@Դուք կարող եք օգտագործել Rufus (3.15+) կրիչում ձայնագրելու համար, որպեսզի ավարտեք Ventoy-ի տեղադրումը:",
"STR_VTSI_CREATE_FAILED":"VTSI ֆայլի ստեղծումը ձախողվեց։",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
@@ -2088,6 +2384,69 @@
"STR_VTSI_CREATE_TIP":"Tällä kerralla laitteeseen ei kirjoiteta, vaan luodaan ainoastaan VTSI -tiedosto#@Jatketaanko?",
"STR_VTSI_CREATE_SUCCESS":"VTSI -tiedosto luotiin onnistuneesti!#@Voit käyttää Rufus-ohjelmaa(3.15+) kirjoittaaksesi sen laitteeseen viimeistelläksesi Ventoy-asennuksen.",
"STR_VTSI_CREATE_FAILED":"VTSI -tiedoston luominen epäonnistui.",
"STR_MENU_PART_RESIZE":"Non-destructive Install",
"STR_PART_RESIZE_TIP":"Ventoy will try non-destructive installation if possible. #@Continue?",
"STR_PART_RESIZE_SUCCESS":"Congratulations!#@Ventoy non-destructive installation successfully finished.",
"STR_PART_RESIZE_FAILED":"Non-destructive installation failed, Check log.txt for details.",
"STR_PART_RESIZE_UNSUPPORTED":"Ventoy non-destructive installation stopped because some conditions cannot be met. Check log.txt for details.",
"STRXXX":""
},
{
"name":"Galician (Galego)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"gbrea",
"STR_ERROR":"Erro",
"STR_WARNING":"Atención",
"STR_INFO":"Info",
"STR_INCORRECT_DIR":"Por favor, execute no directorio correto!",
"STR_INCORRECT_TREE_DIR":"Non me executes aquí, por favor transfire o pacote de instalación, e execute alí.",
"STR_DEVICE":"Dispositivo",
"STR_LOCAL_VER":"Ventoy na aplicación",
"STR_DISK_VER":"Ventoy no dispositivo",
"STR_STATUS":"Estado - PRONTO",
"STR_INSTALL":"Instalar",
"STR_UPDATE":"Actualizar",
"STR_UPDATE_TIP":"A operación de atualización é segura, os ficheiros ISO non serán alterados.#@Continuar?",
"STR_INSTALL_TIP":"O disco será formatado e perderanse todos os datos.#@Continuar?",
"STR_INSTALL_TIP2":"O disco será formatado e perderanse todos os datos.#@Continuar? (Confirmación)",
"STR_INSTALL_SUCCESS":"Parabéns!#@Ventoy foi instalado con suceso no dispositivo.",
"STR_INSTALL_FAILED":"Un erro ocorreu durante a instalación. Podes reconectar o dispositivo USB e tentar novamente. Verifica o ficheiro log.txt para máis detalles.",
"STR_UPDATE_SUCCESS":"Parabéns!#@Ventoy foi actualizado con suceso no dispositivo.",
"STR_UPDATE_FAILED":"Un erro ocorreu durante a actualización. Podes reconectar o dispositivo USB e tentar novamente. Verifica o ficheiro log.txt para máis detalles.",
"STR_WAIT_PROCESS":"Un proceso está en execución, por favor espera...",
"STR_MENU_OPTION":"Opción",
"STR_MENU_SECURE_BOOT":"Soporte de arranque seguro",
"STR_MENU_PART_CFG":"Configuración da Partición",
"STR_BTN_OK":"OK",
"STR_BTN_CANCEL":"Cancelar",
"STR_PRESERVE_SPACE":"Preservar algún espazo no final do disco",
"STR_SPACE_VAL_INVALID":"Valor inválido para o espazo reservado",
"STR_MENU_CLEAR":"Remover o Ventoy",
"STR_CLEAR_SUCCESS":"O Ventoy foi removido deste dispositivo con suceso.",
"STR_CLEAR_FAILED":"Un erro ocorreu ao remover o Ventoy do disco. Podes reconectar o dispositivo USB e tentar novamente. Verifica o ficheiro log.txt para máis detalles.",
"STR_MENU_PART_STYLE":"Estilo de Partición",
"STR_DISK_2TB_MBR_ERROR":"Por favor seleciona GPT para discos maiores que 2TB",
"STR_SHOW_ALL_DEV":"Mostrar todos os dispositivos",
"STR_PART_ALIGN_4KB":"Aliñar particións con 4KB",
"STR_WEB_COMMUNICATION_ERR":"Erro de comunicación:",
"STR_WEB_REMOTE_ABNORMAL":"Erro de comunicación: remoto anormal",
"STR_WEB_REQUEST_TIMEOUT":"Erro de comunicación: Tempo de espera esgotado",
"STR_WEB_SERVICE_UNAVAILABLE":"Erro de comunicación: Servizo non dispoñible",
"STR_WEB_TOKEN_MISMATCH":"Estado do daemon actualizado, por favor inténtao máis tarde.",
"STR_WEB_SERVICE_BUSY":"O servizo está ocupado, por favor inténtao máis tarde.",
"STR_MENU_VTSI_CREATE":"Xerar arquivo VTSI",
"STR_VTSI_CREATE_TIP":"Non será grabado no dispositivo, desta vez, apenas se xerará un ficheiro VTSI#@Continuar?",
"STR_VTSI_CREATE_SUCCESS":"Arquivo VTSI creado con suceso!#@Podes usar Rufus(3.15+) para grabalo no dispositivo e completar a instalación do Ventoy.",
"STR_VTSI_CREATE_FAILED":"Erro na creación do arquivo VTSI.",
"STR_MENU_PART_RESIZE":"Instalación non destructiva",
"STR_PART_RESIZE_TIP":"Ventoy tentará unha instalación non destructiva, se é posible.#@Continuar?",
"STR_PART_RESIZE_SUCCESS":"Parabéns!#@Instalación non destructiva do Ventoy concluida con suceso.",
"STR_PART_RESIZE_FAILED":"Erro na instalación non destructiva, revisa o arquivo log.txt para ver os detalles.",
"STR_PART_RESIZE_UNSUPPORTED":"Instalación non destructiva do Ventoy interrompida porque non se poden cumprir algunhas condicións. Revisa o arquivo log.txt para mais detalles.",
"STRXXX":""
}
]

View File

@@ -157,7 +157,9 @@ if [ "$1" = "VENTOY_I386_QT_BUILD" ]; then
exit 0
fi
if [ ! -f /opt/CentOS8/LinuxGUI/build.sh ]; then
mount --bind /home/share/Ventoy/LinuxGUI /opt/CentOS8/LinuxGUI
fi
chroot /opt/CentOS8 sh /buildqt.sh
force_copy ./Ventoy2Disk.qt5_32 ../INSTALL/tool/i386/Ventoy2Disk.qt5

78
Plugson/build.sh Normal file
View File

@@ -0,0 +1,78 @@
#!/bin/bash
if [ "$1" = "sim" ]; then
exopt="-DVENTOY_SIM"
fi
build_func() {
libsuffix=$2
toolDir=$3
XXFLAG='-std=gnu99 -D_FILE_OFFSET_BITS=64'
XXLIB=""
echo "CC=$1 libsuffix=$libsuffix toolDir=$toolDir"
echo "CC civetweb.o"
$1 $XXFLAG -c -Wall -Wextra -Wshadow -Wformat-security -Winit-self \
-Wmissing-prototypes -O2 -DLINUX \
-I./src/Lib/libhttp/include \
-DNDEBUG -DNO_CGI -DNO_CACHING -DNO_SSL -DSQLITE_DISABLE_LFS -DSSL_ALREADY_INITIALIZED \
-DUSE_STACK_SIZE=102400 -DNDEBUG -fPIC \
./src/Lib/libhttp/include/civetweb.c \
-o ./civetweb.o
echo "CC plugson.o"
$1 $XXFLAG -O2 $exopt -Wall -Wno-unused-function -DSTATIC=static -DINIT= \
-I./src \
-I./src/Core \
-I./src/Web \
-I./src/Include \
-I./src/Lib/libhttp/include \
-I./src/Lib/fat_io_lib/include \
-I./src/Lib/xz-embedded/linux/include \
-I./src/Lib/xz-embedded/linux/include/linux \
-I./src/Lib/xz-embedded/userspace \
-I ./src/Lib/exfat/src/libexfat \
-I ./src/Lib/exfat/src/mkfs \
-I ./src/Lib/fat_io_lib \
\
-L ./src/Lib/fat_io_lib/lib \
src/main_linux.c \
src/Core/ventoy_crc32.c \
src/Core/ventoy_disk.c \
src/Core/ventoy_disk_linux.c \
src/Core/ventoy_json.c \
src/Core/ventoy_log.c \
src/Core/ventoy_md5.c \
src/Core/ventoy_util.c \
src/Core/ventoy_util_linux.c \
src/Web/*.c \
src/Lib/xz-embedded/linux/lib/decompress_unxz.c \
src/Lib/fat_io_lib/*.c \
$XXLIB \
-l pthread \
./civetweb.o \
-o Plugson$libsuffix
rm -f *.o
if [ "$libsuffix" = "aa64" ]; then
aarch64-linux-gnu-strip Plugson$libsuffix
elif [ "$libsuffix" = "m64e" ]; then
mips-linux-gnu-strip Plugson$libsuffix
else
strip Plugson$libsuffix
fi
rm -f ../INSTALL/tool/$toolDir/Plugson
cp -a Plugson$libsuffix ../INSTALL/tool/$toolDir/Plugson
}
build_func "gcc" '64' 'x86_64'
build_func "gcc -m32" '32' 'i386'
build_func "aarch64-linux-gnu-gcc" 'aa64' 'aarch64'
build_func "mips-linux-gnu-gcc -mips64r2 -mabi=64" 'm64e' 'mips64el'

39
Plugson/pack.sh Normal file
View File

@@ -0,0 +1,39 @@
#!/bin/sh
if [ -n "$PKG_DATE" ]; then
plugson_verion=$PKG_DATE
else
plugson_verion=$(date '+%Y%m%d %H:%M:%S')
fi
sed "s#.*plugson_build_date.*# <b id=\"plugson_build_date\">$plugson_verion</b>#" -i ./www/index.html
if [ ! -f ./vs/VentoyPlugson/Release/VentoyPlugson.exe ]; then
echo "NO VentoyPlugson.exe found"
exit 1
fi
if [ -f ./www.tar.xz ]; then
rm -f ./www.tar.xz
fi
[ -f ./www/helplist ] && rm -f ./www/helplist
ls -1 ../INSTALL/grub/help/ | while read line; do
echo -n ${line:0:5} >> ./www/helplist
done
echo -n "$plugson_verion" > ./www/buildtime
tar cf www.tar www
xz --check=crc32 www.tar
rm -f ../INSTALL/VentoyPlugson.exe
cp -a ./vs/VentoyPlugson/Release/VentoyPlugson.exe ../INSTALL/VentoyPlugson.exe
rm -f ../INSTALL/tool/plugson.tar.xz
mv ./www.tar.xz ../INSTALL/tool/plugson.tar.xz
echo ""
echo "========= SUCCESS ==========="
echo ""

View File

@@ -0,0 +1,304 @@
/******************************************************************************
* crc32.c ---- ventoy crc32
*
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#if defined(_MSC_VER) || defined(WIN32)
#include <Windows.h>
#define uint32_t UINT32
#else
#include <unistd.h>
#endif
static uint32_t g_crc_table[256] = {
0x00000000,
0x77073096,
0xEE0E612C,
0x990951BA,
0x076DC419,
0x706AF48F,
0xE963A535,
0x9E6495A3,
0x0EDB8832,
0x79DCB8A4,
0xE0D5E91E,
0x97D2D988,
0x09B64C2B,
0x7EB17CBD,
0xE7B82D07,
0x90BF1D91,
0x1DB71064,
0x6AB020F2,
0xF3B97148,
0x84BE41DE,
0x1ADAD47D,
0x6DDDE4EB,
0xF4D4B551,
0x83D385C7,
0x136C9856,
0x646BA8C0,
0xFD62F97A,
0x8A65C9EC,
0x14015C4F,
0x63066CD9,
0xFA0F3D63,
0x8D080DF5,
0x3B6E20C8,
0x4C69105E,
0xD56041E4,
0xA2677172,
0x3C03E4D1,
0x4B04D447,
0xD20D85FD,
0xA50AB56B,
0x35B5A8FA,
0x42B2986C,
0xDBBBC9D6,
0xACBCF940,
0x32D86CE3,
0x45DF5C75,
0xDCD60DCF,
0xABD13D59,
0x26D930AC,
0x51DE003A,
0xC8D75180,
0xBFD06116,
0x21B4F4B5,
0x56B3C423,
0xCFBA9599,
0xB8BDA50F,
0x2802B89E,
0x5F058808,
0xC60CD9B2,
0xB10BE924,
0x2F6F7C87,
0x58684C11,
0xC1611DAB,
0xB6662D3D,
0x76DC4190,
0x01DB7106,
0x98D220BC,
0xEFD5102A,
0x71B18589,
0x06B6B51F,
0x9FBFE4A5,
0xE8B8D433,
0x7807C9A2,
0x0F00F934,
0x9609A88E,
0xE10E9818,
0x7F6A0DBB,
0x086D3D2D,
0x91646C97,
0xE6635C01,
0x6B6B51F4,
0x1C6C6162,
0x856530D8,
0xF262004E,
0x6C0695ED,
0x1B01A57B,
0x8208F4C1,
0xF50FC457,
0x65B0D9C6,
0x12B7E950,
0x8BBEB8EA,
0xFCB9887C,
0x62DD1DDF,
0x15DA2D49,
0x8CD37CF3,
0xFBD44C65,
0x4DB26158,
0x3AB551CE,
0xA3BC0074,
0xD4BB30E2,
0x4ADFA541,
0x3DD895D7,
0xA4D1C46D,
0xD3D6F4FB,
0x4369E96A,
0x346ED9FC,
0xAD678846,
0xDA60B8D0,
0x44042D73,
0x33031DE5,
0xAA0A4C5F,
0xDD0D7CC9,
0x5005713C,
0x270241AA,
0xBE0B1010,
0xC90C2086,
0x5768B525,
0x206F85B3,
0xB966D409,
0xCE61E49F,
0x5EDEF90E,
0x29D9C998,
0xB0D09822,
0xC7D7A8B4,
0x59B33D17,
0x2EB40D81,
0xB7BD5C3B,
0xC0BA6CAD,
0xEDB88320,
0x9ABFB3B6,
0x03B6E20C,
0x74B1D29A,
0xEAD54739,
0x9DD277AF,
0x04DB2615,
0x73DC1683,
0xE3630B12,
0x94643B84,
0x0D6D6A3E,
0x7A6A5AA8,
0xE40ECF0B,
0x9309FF9D,
0x0A00AE27,
0x7D079EB1,
0xF00F9344,
0x8708A3D2,
0x1E01F268,
0x6906C2FE,
0xF762575D,
0x806567CB,
0x196C3671,
0x6E6B06E7,
0xFED41B76,
0x89D32BE0,
0x10DA7A5A,
0x67DD4ACC,
0xF9B9DF6F,
0x8EBEEFF9,
0x17B7BE43,
0x60B08ED5,
0xD6D6A3E8,
0xA1D1937E,
0x38D8C2C4,
0x4FDFF252,
0xD1BB67F1,
0xA6BC5767,
0x3FB506DD,
0x48B2364B,
0xD80D2BDA,
0xAF0A1B4C,
0x36034AF6,
0x41047A60,
0xDF60EFC3,
0xA867DF55,
0x316E8EEF,
0x4669BE79,
0xCB61B38C,
0xBC66831A,
0x256FD2A0,
0x5268E236,
0xCC0C7795,
0xBB0B4703,
0x220216B9,
0x5505262F,
0xC5BA3BBE,
0xB2BD0B28,
0x2BB45A92,
0x5CB36A04,
0xC2D7FFA7,
0xB5D0CF31,
0x2CD99E8B,
0x5BDEAE1D,
0x9B64C2B0,
0xEC63F226,
0x756AA39C,
0x026D930A,
0x9C0906A9,
0xEB0E363F,
0x72076785,
0x05005713,
0x95BF4A82,
0xE2B87A14,
0x7BB12BAE,
0x0CB61B38,
0x92D28E9B,
0xE5D5BE0D,
0x7CDCEFB7,
0x0BDBDF21,
0x86D3D2D4,
0xF1D4E242,
0x68DDB3F8,
0x1FDA836E,
0x81BE16CD,
0xF6B9265B,
0x6FB077E1,
0x18B74777,
0x88085AE6,
0xFF0F6A70,
0x66063BCA,
0x11010B5C,
0x8F659EFF,
0xF862AE69,
0x616BFFD3,
0x166CCF45,
0xA00AE278,
0xD70DD2EE,
0x4E048354,
0x3903B3C2,
0xA7672661,
0xD06016F7,
0x4969474D,
0x3E6E77DB,
0xAED16A4A,
0xD9D65ADC,
0x40DF0B66,
0x37D83BF0,
0xA9BCAE53,
0xDEBB9EC5,
0x47B2CF7F,
0x30B5FFE9,
0xBDBDF21C,
0xCABAC28A,
0x53B39330,
0x24B4A3A6,
0xBAD03605,
0xCDD70693,
0x54DE5729,
0x23D967BF,
0xB3667A2E,
0xC4614AB8,
0x5D681B02,
0x2A6F2B94,
0xB40BBE37,
0xC30C8EA1,
0x5A05DF1B,
0x2D02EF8D
};
uint32_t ventoy_crc32(void *Buffer, uint32_t Length)
{
uint32_t i;
uint8_t *Ptr = Buffer;
uint32_t Crc = 0xFFFFFFFF;
for (i = 0; i < Length; i++, Ptr++)
{
Crc = (Crc >> 8) ^ g_crc_table[(uint8_t) Crc ^ *Ptr];
}
return Crc ^ 0xffffffff;
}

View File

@@ -0,0 +1,207 @@
/******************************************************************************
* ventoy_define.h
*
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __VENTOY_DEFINE_H__
#define __VENTOY_DEFINE_H__
#if defined(_MSC_VER) || defined(WIN32)
#include <windows.h>
#include <stdint.h>
#else
#include <stdint.h>
#include <stdarg.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#include <linux/limits.h>
#endif
#define LOG_FILE "VentoyPlugson.log"
#define SIZE_1MB 1048576
#define SIZE_1GB 1073741824
#define JSON_BUF_MAX (8 * SIZE_1MB)
#define TAR_BUF_MAX (8 * SIZE_1MB)
#define VTOYIMG_PART_START_BYTES (1024 * 1024)
#define VTOYIMG_PART_START_SECTOR 2048
#define VTOYEFI_PART_BYTES (32 * 1024 * 1024)
#define VTOYEFI_PART_SECTORS 65536
#pragma pack(1)
typedef struct vtoy_guid
{
uint32_t data1;
uint16_t data2;
uint16_t data3;
uint8_t data4[8];
}vtoy_guid;
typedef struct PART_TABLE
{
uint8_t Active; // 0x00 0x80
uint8_t StartHead;
uint16_t StartSector : 6;
uint16_t StartCylinder : 10;
uint8_t FsFlag;
uint8_t EndHead;
uint16_t EndSector : 6;
uint16_t EndCylinder : 10;
uint32_t StartSectorId;
uint32_t SectorCount;
}PART_TABLE;
typedef struct MBR_HEAD
{
uint8_t BootCode[446];
PART_TABLE PartTbl[4];
uint8_t Byte55;
uint8_t ByteAA;
}MBR_HEAD;
typedef struct VTOY_GPT_HDR
{
char Signature[8]; /* EFI PART */
uint8_t Version[4];
uint32_t Length;
uint32_t Crc;
uint8_t Reserved1[4];
uint64_t EfiStartLBA;
uint64_t EfiBackupLBA;
uint64_t PartAreaStartLBA;
uint64_t PartAreaEndLBA;
vtoy_guid DiskGuid;
uint64_t PartTblStartLBA;
uint32_t PartTblTotNum;
uint32_t PartTblEntryLen;
uint32_t PartTblCrc;
uint8_t Reserved2[420];
}VTOY_GPT_HDR;
typedef struct VTOY_GPT_PART_TBL
{
vtoy_guid PartType;
vtoy_guid PartGuid;
uint64_t StartLBA;
uint64_t LastLBA;
uint64_t Attr;
uint16_t Name[36];
}VTOY_GPT_PART_TBL;
typedef struct VTOY_GPT_INFO
{
MBR_HEAD MBR;
VTOY_GPT_HDR Head;
VTOY_GPT_PART_TBL PartTbl[128];
}VTOY_GPT_INFO;
#pragma pack()
#define MBR_PART_STYLE 0
#define GPT_PART_STYLE 1
#pragma pack(1)
typedef struct ventoy_guid
{
uint32_t data1;
uint16_t data2;
uint16_t data3;
uint8_t data4[8];
}ventoy_guid;
#pragma pack()
#ifndef O_BINARY
#define O_BINARY 0
#endif
#define VLOG_LOG 1
#define VLOG_DEBUG 2
#define ulong unsigned long
#define _ll long long
#define _ull unsigned long long
#if defined(_MSC_VER) || defined(WIN32)
#define strlcpy(dst, src) strcpy_s(dst, sizeof(dst), src)
#define scnprintf(dst, len, fmt, ...) sprintf_s(dst, len, fmt, ##__VA_ARGS__)
#define vlog(fmt, ...) ventoy_syslog(VLOG_LOG, fmt, ##__VA_ARGS__)
#define vdebug(fmt, ...) ventoy_syslog(VLOG_DEBUG, fmt, ##__VA_ARGS__)
#define localtime_r(a,b) localtime_s(b,a)
#define LASTERR GetLastError()
#define CHECK_CLOSE_HANDLE(Handle) \
{\
if (Handle != INVALID_HANDLE_VALUE) \
{\
CloseHandle(Handle); \
Handle = INVALID_HANDLE_VALUE; \
}\
}
#else
#define strlcpy(dst, src) strncpy(dst, src, sizeof(dst) - 1)
#define scnprintf(dst, len, fmt, args...) snprintf(dst, len, fmt, ##args)
#define vlog(fmt, args...) ventoy_syslog(VLOG_LOG, fmt, ##args)
#define vdebug(fmt, args...) ventoy_syslog(VLOG_DEBUG, fmt, ##args)
#define MAX_PATH PATH_MAX
#endif
#define CHECK_FREE(p) \
{\
if (p)\
{\
free(p); \
(p) = NULL; \
}\
}
void ventoy_syslog(int level, const char *Fmt, ...);
void ventoy_set_loglevel(int level);
uint32_t ventoy_crc32(void *Buffer, uint32_t Length);
#if defined(_MSC_VER) || defined(WIN32)
static __inline void * zalloc(size_t n)
#else
static inline void * zalloc(size_t n)
#endif
{
void *p = malloc(n);
if (p) memset(p, 0, n);
return p;
}
#endif /* __VENTOY_DEFINE_H__ */

View File

@@ -0,0 +1,24 @@
/******************************************************************************
* ventoy_disk.c ---- ventoy disk
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

View File

@@ -0,0 +1,166 @@
/******************************************************************************
* ventoy_disk.h
*
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __VENTOY_DISK_H__
#define __VENTOY_DISK_H__
#define MAX_DISK 256
typedef struct ventoy_disk
{
char devname[64];
int pathcase;
char cur_fsname[64];
char cur_capacity[64];
char cur_model[256];
char cur_ventoy_ver[64];
int cur_secureboot;
int cur_part_style;
}ventoy_disk;
#if defined(_MSC_VER) || defined(WIN32)
#else
typedef enum
{
VTOY_DEVICE_UNKNOWN = 0,
VTOY_DEVICE_SCSI,
VTOY_DEVICE_USB,
VTOY_DEVICE_IDE,
VTOY_DEVICE_DAC960,
VTOY_DEVICE_CPQARRAY,
VTOY_DEVICE_FILE,
VTOY_DEVICE_ATARAID,
VTOY_DEVICE_I2O,
VTOY_DEVICE_UBD,
VTOY_DEVICE_DASD,
VTOY_DEVICE_VIODASD,
VTOY_DEVICE_SX8,
VTOY_DEVICE_DM,
VTOY_DEVICE_XVD,
VTOY_DEVICE_SDMMC,
VTOY_DEVICE_VIRTBLK,
VTOY_DEVICE_AOE,
VTOY_DEVICE_MD,
VTOY_DEVICE_LOOP,
VTOY_DEVICE_NVME,
VTOY_DEVICE_RAM,
VTOY_DEVICE_PMEM,
VTOY_DEVICE_END
}ventoy_dev_type;
/* from <linux/major.h> */
#define IDE0_MAJOR 3
#define IDE1_MAJOR 22
#define IDE2_MAJOR 33
#define IDE3_MAJOR 34
#define IDE4_MAJOR 56
#define IDE5_MAJOR 57
#define SCSI_CDROM_MAJOR 11
#define SCSI_DISK0_MAJOR 8
#define SCSI_DISK1_MAJOR 65
#define SCSI_DISK2_MAJOR 66
#define SCSI_DISK3_MAJOR 67
#define SCSI_DISK4_MAJOR 68
#define SCSI_DISK5_MAJOR 69
#define SCSI_DISK6_MAJOR 70
#define SCSI_DISK7_MAJOR 71
#define SCSI_DISK8_MAJOR 128
#define SCSI_DISK9_MAJOR 129
#define SCSI_DISK10_MAJOR 130
#define SCSI_DISK11_MAJOR 131
#define SCSI_DISK12_MAJOR 132
#define SCSI_DISK13_MAJOR 133
#define SCSI_DISK14_MAJOR 134
#define SCSI_DISK15_MAJOR 135
#define COMPAQ_SMART2_MAJOR 72
#define COMPAQ_SMART2_MAJOR1 73
#define COMPAQ_SMART2_MAJOR2 74
#define COMPAQ_SMART2_MAJOR3 75
#define COMPAQ_SMART2_MAJOR4 76
#define COMPAQ_SMART2_MAJOR5 77
#define COMPAQ_SMART2_MAJOR6 78
#define COMPAQ_SMART2_MAJOR7 79
#define COMPAQ_SMART_MAJOR 104
#define COMPAQ_SMART_MAJOR1 105
#define COMPAQ_SMART_MAJOR2 106
#define COMPAQ_SMART_MAJOR3 107
#define COMPAQ_SMART_MAJOR4 108
#define COMPAQ_SMART_MAJOR5 109
#define COMPAQ_SMART_MAJOR6 110
#define COMPAQ_SMART_MAJOR7 111
#define DAC960_MAJOR 48
#define ATARAID_MAJOR 114
#define I2O_MAJOR1 80
#define I2O_MAJOR2 81
#define I2O_MAJOR3 82
#define I2O_MAJOR4 83
#define I2O_MAJOR5 84
#define I2O_MAJOR6 85
#define I2O_MAJOR7 86
#define I2O_MAJOR8 87
#define UBD_MAJOR 98
#define DASD_MAJOR 94
#define VIODASD_MAJOR 112
#define AOE_MAJOR 152
#define SX8_MAJOR1 160
#define SX8_MAJOR2 161
#define XVD_MAJOR 202
#define SDMMC_MAJOR 179
#define LOOP_MAJOR 7
#define MD_MAJOR 9
#define BLKEXT_MAJOR 259
#define RAM_MAJOR 1
#define SCSI_BLK_MAJOR(M) ( \
(M) == SCSI_DISK0_MAJOR \
|| (M) == SCSI_CDROM_MAJOR \
|| ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR) \
|| ((M) >= SCSI_DISK8_MAJOR && (M) <= SCSI_DISK15_MAJOR))
#define IDE_BLK_MAJOR(M) \
((M) == IDE0_MAJOR || \
(M) == IDE1_MAJOR || \
(M) == IDE2_MAJOR || \
(M) == IDE3_MAJOR || \
(M) == IDE4_MAJOR || \
(M) == IDE5_MAJOR)
#define SX8_BLK_MAJOR(M) ((M) >= SX8_MAJOR1 && (M) <= SX8_MAJOR2)
#define I2O_BLK_MAJOR(M) ((M) >= I2O_MAJOR1 && (M) <= I2O_MAJOR8)
#define CPQARRAY_BLK_MAJOR(M) \
(((M) >= COMPAQ_SMART2_MAJOR && (M) <= COMPAQ_SMART2_MAJOR7) || \
(COMPAQ_SMART_MAJOR <= (M) && (M) <= COMPAQ_SMART_MAJOR7))
#endif
int ventoy_disk_init(void);
void ventoy_disk_exit(void);
int ventoy_get_disk_info(char **argv);
const ventoy_disk * ventoy_get_disk_list(int *num);
const ventoy_disk * ventoy_get_disk_node(int id);
int CheckRuntimeEnvironment(char Letter, ventoy_disk *disk);
#endif /* __VENTOY_DISK_H__ */

View File

@@ -0,0 +1,607 @@
/******************************************************************************
* ventoy_disk.c ---- ventoy disk
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <linux/fs.h>
#include <dirent.h>
#include <time.h>
#include <ventoy_define.h>
#include <ventoy_disk.h>
#include <ventoy_util.h>
#include <fat_filelib.h>
static int g_fatlib_media_fd = 0;
static uint64_t g_fatlib_media_offset = 0;
static const char *g_ventoy_dev_type_str[VTOY_DEVICE_END] =
{
"unknown", "scsi", "USB", "ide", "dac960",
"cpqarray", "file", "ataraid", "i2o",
"ubd", "dasd", "viodasd", "sx8", "dm",
"xvd", "sd/mmc", "virtblk", "aoe",
"md", "loopback", "nvme", "brd", "pmem"
};
static const char * ventoy_get_dev_type_name(ventoy_dev_type type)
{
return (type < VTOY_DEVICE_END) ? g_ventoy_dev_type_str[type] : "unknown";
}
static int ventoy_check_blk_major(int major, const char *type)
{
int flag = 0;
int valid = 0;
int devnum = 0;
int len = 0;
char line[64];
char *pos = NULL;
FILE *fp = NULL;
fp = fopen("/proc/devices", "r");
if (!fp)
{
return 0;
}
len = (int)strlen(type);
while (fgets(line, sizeof(line), fp))
{
if (flag)
{
pos = strchr(line, ' ');
if (pos)
{
devnum = (int)strtol(line, NULL, 10);
if (devnum == major)
{
if (strncmp(pos + 1, type, len) == 0)
{
valid = 1;
}
break;
}
}
}
else if (strncmp(line, "Block devices:", 14) == 0)
{
flag = 1;
}
}
fclose(fp);
return valid;
}
static int ventoy_get_disk_devnum(const char *name, int *major, int* minor)
{
int rc;
char *pos;
char devnum[16] = {0};
rc = ventoy_get_sys_file_line(devnum, sizeof(devnum), "/sys/block/%s/dev", name);
if (rc)
{
return 1;
}
pos = strstr(devnum, ":");
if (!pos)
{
return 1;
}
*major = (int)strtol(devnum, NULL, 10);
*minor = (int)strtol(pos + 1, NULL, 10);
return 0;
}
static ventoy_dev_type ventoy_get_dev_type(const char *name, int major, int minor)
{
int rc;
char syspath[128];
char dstpath[256];
memset(syspath, 0, sizeof(syspath));
memset(dstpath, 0, sizeof(dstpath));
scnprintf(syspath, sizeof(syspath), "/sys/block/%s", name);
rc = readlink(syspath, dstpath, sizeof(dstpath) - 1);
if (rc > 0 && strstr(dstpath, "/usb"))
{
return VTOY_DEVICE_USB;
}
if (SCSI_BLK_MAJOR(major) && (minor % 0x10 == 0))
{
return VTOY_DEVICE_SCSI;
}
else if (IDE_BLK_MAJOR(major) && (minor % 0x40 == 0))
{
return VTOY_DEVICE_IDE;
}
else if (major == DAC960_MAJOR && (minor % 0x8 == 0))
{
return VTOY_DEVICE_DAC960;
}
else if (major == ATARAID_MAJOR && (minor % 0x10 == 0))
{
return VTOY_DEVICE_ATARAID;
}
else if (major == AOE_MAJOR && (minor % 0x10 == 0))
{
return VTOY_DEVICE_AOE;
}
else if (major == DASD_MAJOR && (minor % 0x4 == 0))
{
return VTOY_DEVICE_DASD;
}
else if (major == VIODASD_MAJOR && (minor % 0x8 == 0))
{
return VTOY_DEVICE_VIODASD;
}
else if (SX8_BLK_MAJOR(major) && (minor % 0x20 == 0))
{
return VTOY_DEVICE_SX8;
}
else if (I2O_BLK_MAJOR(major) && (minor % 0x10 == 0))
{
return VTOY_DEVICE_I2O;
}
else if (CPQARRAY_BLK_MAJOR(major) && (minor % 0x10 == 0))
{
return VTOY_DEVICE_CPQARRAY;
}
else if (UBD_MAJOR == major && (minor % 0x10 == 0))
{
return VTOY_DEVICE_UBD;
}
else if (XVD_MAJOR == major && (minor % 0x10 == 0))
{
return VTOY_DEVICE_XVD;
}
else if (SDMMC_MAJOR == major && (minor % 0x8 == 0))
{
return VTOY_DEVICE_SDMMC;
}
else if (ventoy_check_blk_major(major, "virtblk"))
{
return VTOY_DEVICE_VIRTBLK;
}
else if (major == LOOP_MAJOR)
{
return VTOY_DEVICE_LOOP;
}
else if (major == MD_MAJOR)
{
return VTOY_DEVICE_MD;
}
else if (major == RAM_MAJOR)
{
return VTOY_DEVICE_RAM;
}
else if (strstr(name, "nvme") && ventoy_check_blk_major(major, "blkext"))
{
return VTOY_DEVICE_NVME;
}
else if (strstr(name, "pmem") && ventoy_check_blk_major(major, "blkext"))
{
return VTOY_DEVICE_PMEM;
}
return VTOY_DEVICE_END;
}
static int ventoy_is_possible_blkdev(const char *name)
{
if (name[0] == '.')
{
return 0;
}
/* /dev/ramX */
if (name[0] == 'r' && name[1] == 'a' && name[2] == 'm')
{
return 0;
}
/* /dev/zramX */
if (name[0] == 'z' && name[1] == 'r' && name[2] == 'a' && name[3] == 'm')
{
return 0;
}
/* /dev/loopX */
if (name[0] == 'l' && name[1] == 'o' && name[2] == 'o' && name[3] == 'p')
{
return 0;
}
/* /dev/dm-X */
if (name[0] == 'd' && name[1] == 'm' && name[2] == '-' && isdigit(name[3]))
{
return 0;
}
/* /dev/srX */
if (name[0] == 's' && name[1] == 'r' && isdigit(name[2]))
{
return 0;
}
return 1;
}
uint64_t ventoy_get_disk_size_in_byte(const char *disk)
{
int fd;
int rc;
unsigned long long size = 0;
char diskpath[256] = {0};
char sizebuf[64] = {0};
// Try 1: get size from sysfs
scnprintf(diskpath, sizeof(diskpath) - 1, "/sys/block/%s/size", disk);
if (access(diskpath, F_OK) >= 0)
{
vdebug("get disk size from sysfs for %s\n", disk);
fd = open(diskpath, O_RDONLY | O_BINARY);
if (fd >= 0)
{
read(fd, sizebuf, sizeof(sizebuf));
size = strtoull(sizebuf, NULL, 10);
close(fd);
return (uint64_t)(size * 512);
}
}
else
{
vdebug("%s not exist \n", diskpath);
}
// Try 2: get size from ioctl
scnprintf(diskpath, sizeof(diskpath) - 1, "/dev/%s", disk);
fd = open(diskpath, O_RDONLY);
if (fd >= 0)
{
vdebug("get disk size from ioctl for %s\n", disk);
rc = ioctl(fd, BLKGETSIZE64, &size);
if (rc == -1)
{
size = 0;
vdebug("failed to ioctl %d\n", rc);
}
close(fd);
}
else
{
vdebug("failed to open %s %d\n", diskpath, errno);
}
vdebug("disk %s size %llu bytes\n", disk, size);
return size;
}
int ventoy_get_disk_vendor(const char *name, char *vendorbuf, int bufsize)
{
return ventoy_get_sys_file_line(vendorbuf, bufsize, "/sys/block/%s/device/vendor", name);
}
int ventoy_get_disk_model(const char *name, char *modelbuf, int bufsize)
{
return ventoy_get_sys_file_line(modelbuf, bufsize, "/sys/block/%s/device/model", name);
}
static int fatlib_media_sector_read(uint32 sector, uint8 *buffer, uint32 sector_count)
{
lseek(g_fatlib_media_fd, (sector + g_fatlib_media_offset) * 512ULL, SEEK_SET);
read(g_fatlib_media_fd, buffer, sector_count * 512);
return 1;
}
static int fatlib_is_secure_boot_enable(void)
{
void *flfile = NULL;
flfile = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
if (flfile)
{
vlog("/EFI/BOOT/grubx64_real.efi find, secure boot in enabled\n");
fl_fclose(flfile);
return 1;
}
else
{
vlog("/EFI/BOOT/grubx64_real.efi not exist\n");
}
return 0;
}
static int fatlib_get_ventoy_version(char *verbuf, int bufsize)
{
int rc = 1;
int size = 0;
char *buf = NULL;
char *pos = NULL;
char *end = NULL;
void *flfile = NULL;
flfile = fl_fopen("/grub/grub.cfg", "rb");
if (flfile)
{
fl_fseek(flfile, 0, SEEK_END);
size = (int)fl_ftell(flfile);
fl_fseek(flfile, 0, SEEK_SET);
buf = malloc(size + 1);
if (buf)
{
fl_fread(buf, 1, size, flfile);
buf[size] = 0;
pos = strstr(buf, "VENTOY_VERSION=");
if (pos)
{
pos += strlen("VENTOY_VERSION=");
if (*pos == '"')
{
pos++;
}
end = pos;
while (*end != 0 && *end != '"' && *end != '\r' && *end != '\n')
{
end++;
}
*end = 0;
scnprintf(verbuf, bufsize - 1, "%s", pos);
rc = 0;
}
free(buf);
}
fl_fclose(flfile);
}
else
{
vdebug("No grub.cfg found\n");
}
return rc;
}
/* <BEGIN>: Deleted by longpanda, 20211028 PN:XX LABEL:XX */
#if 0
int ventoy_get_vtoy_data(ventoy_disk *info, int *ppartstyle)
{
int i;
int fd;
int len;
int rc = 1;
int ret = 1;
int part_style;
uint64_t part1_start_sector;
uint64_t part1_sector_count;
uint64_t part2_start_sector;
uint64_t part2_sector_count;
uint64_t preserved_space;
char name[64] = {0};
disk_ventoy_data *vtoy = NULL;
VTOY_GPT_INFO *gpt = NULL;
vtoy = &(info->vtoydata);
gpt = &(vtoy->gptinfo);
memset(vtoy, 0, sizeof(disk_ventoy_data));
vdebug("ventoy_get_vtoy_data %s\n", info->disk_path);
if (info->size_in_byte < (2 * VTOYEFI_PART_BYTES))
{
vdebug("disk %s is too small %llu\n", info->disk_path, (_ull)info->size_in_byte);
return 1;
}
fd = open(info->disk_path, O_RDONLY | O_BINARY);
if (fd < 0)
{
vdebug("failed to open %s %d\n", info->disk_path, errno);
return 1;
}
len = (int)read(fd, &(vtoy->gptinfo), sizeof(VTOY_GPT_INFO));
if (len != sizeof(VTOY_GPT_INFO))
{
vdebug("failed to read %s %d\n", info->disk_path, errno);
goto end;
}
if (gpt->MBR.Byte55 != 0x55 || gpt->MBR.ByteAA != 0xAA)
{
vdebug("Invalid mbr magic 0x%x 0x%x\n", gpt->MBR.Byte55, gpt->MBR.ByteAA);
goto end;
}
if (gpt->MBR.PartTbl[0].FsFlag == 0xEE && strncmp(gpt->Head.Signature, "EFI PART", 8) == 0)
{
part_style = GPT_PART_STYLE;
if (ppartstyle)
{
*ppartstyle = part_style;
}
if (gpt->PartTbl[0].StartLBA == 0 || gpt->PartTbl[1].StartLBA == 0)
{
vdebug("NO ventoy efi part layout <%llu %llu>\n",
(_ull)gpt->PartTbl[0].StartLBA,
(_ull)gpt->PartTbl[1].StartLBA);
goto end;
}
for (i = 0; i < 36; i++)
{
name[i] = (char)(gpt->PartTbl[1].Name[i]);
}
if (strcmp(name, "VTOYEFI"))
{
vdebug("Invalid efi part2 name <%s>\n", name);
goto end;
}
part1_start_sector = gpt->PartTbl[0].StartLBA;
part1_sector_count = gpt->PartTbl[0].LastLBA - part1_start_sector + 1;
part2_start_sector = gpt->PartTbl[1].StartLBA;
part2_sector_count = gpt->PartTbl[1].LastLBA - part2_start_sector + 1;
preserved_space = info->size_in_byte - (part2_start_sector + part2_sector_count + 33) * 512;
}
else
{
part_style = MBR_PART_STYLE;
if (ppartstyle)
{
*ppartstyle = part_style;
}
part1_start_sector = gpt->MBR.PartTbl[0].StartSectorId;
part1_sector_count = gpt->MBR.PartTbl[0].SectorCount;
part2_start_sector = gpt->MBR.PartTbl[1].StartSectorId;
part2_sector_count = gpt->MBR.PartTbl[1].SectorCount;
preserved_space = info->size_in_byte - (part2_start_sector + part2_sector_count) * 512;
}
if (part1_start_sector != VTOYIMG_PART_START_SECTOR ||
part2_sector_count != VTOYEFI_PART_SECTORS ||
(part1_start_sector + part1_sector_count) != part2_start_sector)
{
vdebug("Not valid ventoy partition layout [%llu %llu] [%llu %llu]\n",
part1_start_sector, part1_sector_count, part2_start_sector, part2_sector_count);
goto end;
}
vdebug("ventoy partition layout check OK: [%llu %llu] [%llu %llu]\n",
part1_start_sector, part1_sector_count, part2_start_sector, part2_sector_count);
vtoy->ventoy_valid = 1;
vdebug("now check secure boot for %s ...\n", info->disk_path);
g_fatlib_media_fd = fd;
g_fatlib_media_offset = part2_start_sector;
fl_init();
if (0 == fl_attach_media(fatlib_media_sector_read, NULL))
{
ret = fatlib_get_ventoy_version(vtoy->ventoy_ver, sizeof(vtoy->ventoy_ver));
if (ret == 0 && vtoy->ventoy_ver[0])
{
vtoy->secure_boot_flag = fatlib_is_secure_boot_enable();
}
else
{
vdebug("fatlib_get_ventoy_version failed %d\n", ret);
}
}
else
{
vdebug("fl_attach_media failed\n");
}
fl_shutdown();
g_fatlib_media_fd = -1;
g_fatlib_media_offset = 0;
if (vtoy->ventoy_ver[0] == 0)
{
vtoy->ventoy_ver[0] = '?';
}
if (0 == vtoy->ventoy_valid)
{
goto end;
}
lseek(fd, 2040 * 512, SEEK_SET);
read(fd, vtoy->rsvdata, sizeof(vtoy->rsvdata));
vtoy->preserved_space = preserved_space;
vtoy->partition_style = part_style;
vtoy->part2_start_sector = part2_start_sector;
rc = 0;
end:
vtoy_safe_close_fd(fd);
return rc;
}
#endif /* #if 0 */
/* <END> : Deleted by longpanda, 20211028 PN:XX LABEL:XX */
int ventoy_get_disk_info(char **argv)
{
uint64_t size;
char vendor[128];
char model[128];
char *disk = argv[4];
if (strncmp(argv[4], "/dev/", 4) == 0)
{
disk += 4;
}
ventoy_get_disk_vendor(disk, vendor, sizeof(vendor));
ventoy_get_disk_model(disk, model, sizeof(model));
scnprintf(g_sysinfo.cur_model, sizeof(g_sysinfo.cur_model), "%s %s [%s]", vendor, model, argv[4]);
strlcpy(g_sysinfo.cur_ventoy_ver, argv[5]);
strlcpy(g_sysinfo.cur_fsname, argv[6]);
g_sysinfo.cur_part_style = (int)strtol(argv[7], NULL, 10);
g_sysinfo.cur_secureboot = (int)strtol(argv[8], NULL, 10);
size = ventoy_get_disk_size_in_byte(disk);
scnprintf(g_sysinfo.cur_capacity, sizeof(g_sysinfo.cur_capacity), "%dGB", (int)ventoy_get_human_readable_gb(size));
return 0;
}
int ventoy_disk_init(void)
{
return 0;
}
void ventoy_disk_exit(void)
{
}

View File

@@ -0,0 +1,88 @@
/******************************************************************************
* ventoy_disk.c ---- ventoy disk
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include <windows.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include <ventoy_define.h>
#include <ventoy_disk.h>
#include <ventoy_util.h>
#include <fat_filelib.h>
static int g_disk_num = 0;
ventoy_disk *g_disk_list = NULL;
int ventoy_disk_init(void)
{
char Letter = 'A';
DWORD Drives = GetLogicalDrives();
vlog("ventoy disk init ...\n");
g_disk_list = zalloc(sizeof(ventoy_disk) * MAX_DISK);
while (Drives)
{
if (Drives & 0x01)
{
if (CheckRuntimeEnvironment(Letter, g_disk_list + g_disk_num) == 0)
{
g_disk_list[g_disk_num].devname[0] = Letter;
g_disk_num++;
vlog("%C: is ventoy disk\n", Letter);
}
else
{
memset(g_disk_list + g_disk_num, 0, sizeof(ventoy_disk));
vlog("%C: is NOT ventoy disk\n", Letter);
}
}
Letter++;
Drives >>= 1;
}
return 0;
}
void ventoy_disk_exit(void)
{
vlog("ventoy disk exit ...\n");
check_free(g_disk_list);
g_disk_list = NULL;
g_disk_num = 0;
}
const ventoy_disk * ventoy_get_disk_list(int *num)
{
*num = g_disk_num;
return g_disk_list;
}
const ventoy_disk * ventoy_get_disk_node(int id)
{
if (id >= 0 && id < g_disk_num)
{
return g_disk_list + id;
}
return NULL;
}

View File

@@ -0,0 +1,803 @@
/******************************************************************************
* ventoy_json.c
*
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#if defined(_MSC_VER) || defined(WIN32)
#else
#include <unistd.h>
#include <sys/types.h>
#include <linux/limits.h>
#endif
#include <ventoy_define.h>
#include <ventoy_util.h>
#include <ventoy_json.h>
static void vtoy_json_free(VTOY_JSON *pstJsonHead)
{
VTOY_JSON *pstNext = NULL;
while (NULL != pstJsonHead)
{
pstNext = pstJsonHead->pstNext;
if ((pstJsonHead->enDataType < JSON_TYPE_BUTT) && (NULL != pstJsonHead->pstChild))
{
vtoy_json_free(pstJsonHead->pstChild);
}
free(pstJsonHead);
pstJsonHead = pstNext;
}
return;
}
static char *vtoy_json_skip(const char *pcData)
{
while ((NULL != pcData) && ('\0' != *pcData) && (*pcData <= 32))
{
pcData++;
}
return (char *)pcData;
}
VTOY_JSON *vtoy_json_find_item
(
VTOY_JSON *pstJson,
JSON_TYPE enDataType,
const char *szKey
)
{
while (NULL != pstJson)
{
if ((enDataType == pstJson->enDataType) &&
(0 == strcmp(szKey, pstJson->pcName)))
{
return pstJson;
}
pstJson = pstJson->pstNext;
}
return NULL;
}
static int vtoy_json_parse_number
(
VTOY_JSON *pstJson,
const char *pcData,
const char **ppcEnd
)
{
unsigned long Value;
Value = strtoul(pcData, (char **)ppcEnd, 10);
if (*ppcEnd == pcData)
{
vdebug("Failed to parse json number %s.\n", pcData);
return JSON_FAILED;
}
pstJson->enDataType = JSON_TYPE_NUMBER;
pstJson->unData.lValue = Value;
return JSON_SUCCESS;
}
static int vtoy_json_parse_string
(
char *pcNewStart,
char *pcRawStart,
VTOY_JSON *pstJson,
const char *pcData,
const char **ppcEnd
)
{
uint32_t uiLen = 0;
const char *pcPos = NULL;
const char *pcTmp = pcData + 1;
*ppcEnd = pcData;
if ('\"' != *pcData)
{
return JSON_FAILED;
}
pcPos = strchr(pcTmp, '\"');
if ((NULL == pcPos) || (pcPos < pcTmp))
{
vdebug("Invalid string %s.\n", pcData);
return JSON_FAILED;
}
if (*(pcPos - 1) == '\\')
{
for (pcPos++; *pcPos; pcPos++)
{
if (*pcPos == '"' && *(pcPos - 1) != '\\')
{
break;
}
}
if (*pcPos == 0 || pcPos < pcTmp)
{
vdebug("Invalid quotes string %s.", pcData);
return JSON_FAILED;
}
}
*ppcEnd = pcPos + 1;
uiLen = (uint32_t)(unsigned long)(pcPos - pcTmp);
pstJson->enDataType = JSON_TYPE_STRING;
pstJson->unData.pcStrVal = pcNewStart + (pcTmp - pcRawStart);
pstJson->unData.pcStrVal[uiLen] = '\0';
return JSON_SUCCESS;
}
static int vtoy_json_parse_array
(
char *pcNewStart,
char *pcRawStart,
VTOY_JSON *pstJson,
const char *pcData,
const char **ppcEnd
)
{
int Ret = JSON_SUCCESS;
VTOY_JSON *pstJsonChild = NULL;
VTOY_JSON *pstJsonItem = NULL;
const char *pcTmp = pcData + 1;
*ppcEnd = pcData;
pstJson->enDataType = JSON_TYPE_ARRAY;
if ('[' != *pcData)
{
return JSON_FAILED;
}
pcTmp = vtoy_json_skip(pcTmp);
if (']' == *pcTmp)
{
*ppcEnd = pcTmp + 1;
return JSON_SUCCESS;
}
JSON_NEW_ITEM(pstJson->pstChild, JSON_FAILED);
Ret = vtoy_json_parse_value(pcNewStart, pcRawStart, pstJson->pstChild, pcTmp, ppcEnd);
if (JSON_SUCCESS != Ret)
{
vdebug("Failed to parse array child.\n");
return JSON_FAILED;
}
pstJsonChild = pstJson->pstChild;
pcTmp = vtoy_json_skip(*ppcEnd);
while ((NULL != pcTmp) && (',' == *pcTmp))
{
JSON_NEW_ITEM(pstJsonItem, JSON_FAILED);
pstJsonChild->pstNext = pstJsonItem;
pstJsonItem->pstPrev = pstJsonChild;
pstJsonChild = pstJsonItem;
Ret = vtoy_json_parse_value(pcNewStart, pcRawStart, pstJsonChild, vtoy_json_skip(pcTmp + 1), ppcEnd);
if (JSON_SUCCESS != Ret)
{
vdebug("Failed to parse array child.\n");
return JSON_FAILED;
}
pcTmp = vtoy_json_skip(*ppcEnd);
}
if ((NULL != pcTmp) && (']' == *pcTmp))
{
*ppcEnd = pcTmp + 1;
return JSON_SUCCESS;
}
else
{
*ppcEnd = pcTmp;
return JSON_FAILED;
}
}
static int vtoy_json_parse_object
(
char *pcNewStart,
char *pcRawStart,
VTOY_JSON *pstJson,
const char *pcData,
const char **ppcEnd
)
{
int Ret = JSON_SUCCESS;
VTOY_JSON *pstJsonChild = NULL;
VTOY_JSON *pstJsonItem = NULL;
const char *pcTmp = pcData + 1;
*ppcEnd = pcData;
pstJson->enDataType = JSON_TYPE_OBJECT;
if ('{' != *pcData)
{
return JSON_FAILED;
}
pcTmp = vtoy_json_skip(pcTmp);
if ('}' == *pcTmp)
{
*ppcEnd = pcTmp + 1;
return JSON_SUCCESS;
}
JSON_NEW_ITEM(pstJson->pstChild, JSON_FAILED);
Ret = vtoy_json_parse_string(pcNewStart, pcRawStart, pstJson->pstChild, pcTmp, ppcEnd);
if (JSON_SUCCESS != Ret)
{
vdebug("Failed to parse array child.\n");
return JSON_FAILED;
}
pstJsonChild = pstJson->pstChild;
pstJsonChild->pcName = pstJsonChild->unData.pcStrVal;
pstJsonChild->unData.pcStrVal = NULL;
pcTmp = vtoy_json_skip(*ppcEnd);
if ((NULL == pcTmp) || (':' != *pcTmp))
{
*ppcEnd = pcTmp;
return JSON_FAILED;
}
Ret = vtoy_json_parse_value(pcNewStart, pcRawStart, pstJsonChild, vtoy_json_skip(pcTmp + 1), ppcEnd);
if (JSON_SUCCESS != Ret)
{
vdebug("Failed to parse array child.\n");
return JSON_FAILED;
}
pcTmp = vtoy_json_skip(*ppcEnd);
while ((NULL != pcTmp) && (',' == *pcTmp))
{
JSON_NEW_ITEM(pstJsonItem, JSON_FAILED);
pstJsonChild->pstNext = pstJsonItem;
pstJsonItem->pstPrev = pstJsonChild;
pstJsonChild = pstJsonItem;
Ret = vtoy_json_parse_string(pcNewStart, pcRawStart, pstJsonChild, vtoy_json_skip(pcTmp + 1), ppcEnd);
if (JSON_SUCCESS != Ret)
{
vdebug("Failed to parse array child.\n");
return JSON_FAILED;
}
pcTmp = vtoy_json_skip(*ppcEnd);
pstJsonChild->pcName = pstJsonChild->unData.pcStrVal;
pstJsonChild->unData.pcStrVal = NULL;
if ((NULL == pcTmp) || (':' != *pcTmp))
{
*ppcEnd = pcTmp;
return JSON_FAILED;
}
Ret = vtoy_json_parse_value(pcNewStart, pcRawStart, pstJsonChild, vtoy_json_skip(pcTmp + 1), ppcEnd);
if (JSON_SUCCESS != Ret)
{
vdebug("Failed to parse array child.\n");
return JSON_FAILED;
}
pcTmp = vtoy_json_skip(*ppcEnd);
}
if ((NULL != pcTmp) && ('}' == *pcTmp))
{
*ppcEnd = pcTmp + 1;
return JSON_SUCCESS;
}
else
{
*ppcEnd = pcTmp;
return JSON_FAILED;
}
}
int vtoy_json_parse_value
(
char *pcNewStart,
char *pcRawStart,
VTOY_JSON *pstJson,
const char *pcData,
const char **ppcEnd
)
{
pcData = vtoy_json_skip(pcData);
switch (*pcData)
{
case 'n':
{
if (0 == strncmp(pcData, "null", 4))
{
pstJson->enDataType = JSON_TYPE_NULL;
*ppcEnd = pcData + 4;
return JSON_SUCCESS;
}
break;
}
case 'f':
{
if (0 == strncmp(pcData, "false", 5))
{
pstJson->enDataType = JSON_TYPE_BOOL;
pstJson->unData.lValue = 0;
*ppcEnd = pcData + 5;
return JSON_SUCCESS;
}
break;
}
case 't':
{
if (0 == strncmp(pcData, "true", 4))
{
pstJson->enDataType = JSON_TYPE_BOOL;
pstJson->unData.lValue = 1;
*ppcEnd = pcData + 4;
return JSON_SUCCESS;
}
break;
}
case '\"':
{
return vtoy_json_parse_string(pcNewStart, pcRawStart, pstJson, pcData, ppcEnd);
}
case '[':
{
return vtoy_json_parse_array(pcNewStart, pcRawStart, pstJson, pcData, ppcEnd);
}
case '{':
{
return vtoy_json_parse_object(pcNewStart, pcRawStart, pstJson, pcData, ppcEnd);
}
case '-':
{
return vtoy_json_parse_number(pstJson, pcData, ppcEnd);
}
default :
{
if (*pcData >= '0' && *pcData <= '9')
{
return vtoy_json_parse_number(pstJson, pcData, ppcEnd);
}
}
}
*ppcEnd = pcData;
vdebug("Invalid json data %u.\n", (uint8_t)(*pcData));
return JSON_FAILED;
}
VTOY_JSON * vtoy_json_create(void)
{
VTOY_JSON *pstJson = NULL;
pstJson = (VTOY_JSON *)zalloc(sizeof(VTOY_JSON));
if (NULL == pstJson)
{
return NULL;
}
return pstJson;
}
int vtoy_json_parse(VTOY_JSON *pstJson, const char *szJsonData)
{
uint32_t uiMemSize = 0;
int Ret = JSON_SUCCESS;
char *pcNewBuf = NULL;
const char *pcEnd = NULL;
uiMemSize = strlen(szJsonData) + 1;
pcNewBuf = (char *)malloc(uiMemSize);
if (NULL == pcNewBuf)
{
vdebug("Failed to alloc new buf.\n");
return JSON_FAILED;
}
memcpy(pcNewBuf, szJsonData, uiMemSize);
pcNewBuf[uiMemSize - 1] = 0;
Ret = vtoy_json_parse_value(pcNewBuf, (char *)szJsonData, pstJson, szJsonData, &pcEnd);
if (JSON_SUCCESS != Ret)
{
vdebug("Failed to parse json data start=%p, end=%p.\n", szJsonData, pcEnd);
return JSON_FAILED;
}
return JSON_SUCCESS;
}
int vtoy_json_parse_ex(VTOY_JSON *pstJson, const char *szJsonData, int szLen)
{
uint32_t uiMemSize = 0;
int Ret = JSON_SUCCESS;
char *pcNewBuf = NULL;
const char *pcEnd = NULL;
uiMemSize = (uint32_t)szLen;
pcNewBuf = (char *)malloc(uiMemSize + 1);
if (NULL == pcNewBuf)
{
vdebug("Failed to alloc new buf.\n");
return JSON_FAILED;
}
memcpy(pcNewBuf, szJsonData, szLen);
pcNewBuf[uiMemSize] = 0;
Ret = vtoy_json_parse_value(pcNewBuf, (char *)szJsonData, pstJson, szJsonData, &pcEnd);
if (JSON_SUCCESS != Ret)
{
vdebug("Failed to parse json data start=%p, end=%p\n", szJsonData, pcEnd);
return JSON_FAILED;
}
return JSON_SUCCESS;
}
int vtoy_json_scan_parse
(
const VTOY_JSON *pstJson,
uint32_t uiParseNum,
VTOY_JSON_PARSE_S *pstJsonParse
)
{
uint32_t i = 0;
const VTOY_JSON *pstJsonCur = NULL;
VTOY_JSON_PARSE_S *pstCurParse = NULL;
for (pstJsonCur = pstJson; NULL != pstJsonCur; pstJsonCur = pstJsonCur->pstNext)
{
if ((JSON_TYPE_OBJECT == pstJsonCur->enDataType) ||
(JSON_TYPE_ARRAY == pstJsonCur->enDataType))
{
continue;
}
for (i = 0, pstCurParse = NULL; i < uiParseNum; i++)
{
if (0 == strcmp(pstJsonParse[i].pcKey, pstJsonCur->pcName))
{
pstCurParse = pstJsonParse + i;
break;
}
}
if (NULL == pstCurParse)
{
continue;
}
switch (pstJsonCur->enDataType)
{
case JSON_TYPE_NUMBER:
{
if (sizeof(uint32_t) == pstCurParse->uiBufSize)
{
*(uint32_t *)(pstCurParse->pDataBuf) = (uint32_t)pstJsonCur->unData.lValue;
}
else if (sizeof(uint16_t) == pstCurParse->uiBufSize)
{
*(uint16_t *)(pstCurParse->pDataBuf) = (uint16_t)pstJsonCur->unData.lValue;
}
else if (sizeof(uint8_t) == pstCurParse->uiBufSize)
{
*(uint8_t *)(pstCurParse->pDataBuf) = (uint8_t)pstJsonCur->unData.lValue;
}
else if ((pstCurParse->uiBufSize > sizeof(uint64_t)))
{
scnprintf((char *)pstCurParse->pDataBuf, pstCurParse->uiBufSize, "%llu",
(unsigned long long)(pstJsonCur->unData.lValue));
}
else
{
vdebug("Invalid number data buf size %u.\n", pstCurParse->uiBufSize);
}
break;
}
case JSON_TYPE_STRING:
{
scnprintf((char *)pstCurParse->pDataBuf, pstCurParse->uiBufSize, "%s", pstJsonCur->unData.pcStrVal);
break;
}
case JSON_TYPE_BOOL:
{
*(uint8_t *)(pstCurParse->pDataBuf) = (pstJsonCur->unData.lValue) > 0 ? 1 : 0;
break;
}
default :
{
break;
}
}
}
return JSON_SUCCESS;
}
int vtoy_json_scan_array
(
VTOY_JSON *pstJson,
const char *szKey,
VTOY_JSON **ppstArrayItem
)
{
VTOY_JSON *pstJsonItem = NULL;
pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_ARRAY, szKey);
if (NULL == pstJsonItem)
{
vdebug("Key %s is not found in json data.\n", szKey);
return JSON_NOT_FOUND;
}
*ppstArrayItem = pstJsonItem;
return JSON_SUCCESS;
}
int vtoy_json_scan_array_ex
(
VTOY_JSON *pstJson,
const char *szKey,
VTOY_JSON **ppstArrayItem
)
{
VTOY_JSON *pstJsonItem = NULL;
pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_ARRAY, szKey);
if (NULL == pstJsonItem)
{
vdebug("Key %s is not found in json data.\n", szKey);
return JSON_NOT_FOUND;
}
*ppstArrayItem = pstJsonItem->pstChild;
return JSON_SUCCESS;
}
int vtoy_json_scan_object
(
VTOY_JSON *pstJson,
const char *szKey,
VTOY_JSON **ppstObjectItem
)
{
VTOY_JSON *pstJsonItem = NULL;
pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_OBJECT, szKey);
if (NULL == pstJsonItem)
{
vdebug("Key %s is not found in json data.\n", szKey);
return JSON_NOT_FOUND;
}
*ppstObjectItem = pstJsonItem;
return JSON_SUCCESS;
}
int vtoy_json_get_int
(
VTOY_JSON *pstJson,
const char *szKey,
int *piValue
)
{
VTOY_JSON *pstJsonItem = NULL;
pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_NUMBER, szKey);
if (NULL == pstJsonItem)
{
//vdebug("Key %s is not found in json data.\n", szKey);
return JSON_NOT_FOUND;
}
*piValue = (int)pstJsonItem->unData.lValue;
return JSON_SUCCESS;
}
int vtoy_json_get_uint
(
VTOY_JSON *pstJson,
const char *szKey,
uint32_t *puiValue
)
{
VTOY_JSON *pstJsonItem = NULL;
pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_NUMBER, szKey);
if (NULL == pstJsonItem)
{
vdebug("Key %s is not found in json data.\n", szKey);
return JSON_NOT_FOUND;
}
*puiValue = (uint32_t)pstJsonItem->unData.lValue;
return JSON_SUCCESS;
}
int vtoy_json_get_uint64
(
VTOY_JSON *pstJson,
const char *szKey,
uint64_t *pui64Value
)
{
VTOY_JSON *pstJsonItem = NULL;
pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_NUMBER, szKey);
if (NULL == pstJsonItem)
{
vdebug("Key %s is not found in json data.\n", szKey);
return JSON_NOT_FOUND;
}
*pui64Value = (uint64_t)pstJsonItem->unData.lValue;
return JSON_SUCCESS;
}
int vtoy_json_get_bool
(
VTOY_JSON *pstJson,
const char *szKey,
uint8_t *pbValue
)
{
VTOY_JSON *pstJsonItem = NULL;
pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_BOOL, szKey);
if (NULL == pstJsonItem)
{
vdebug("Key %s is not found in json data.\n", szKey);
return JSON_NOT_FOUND;
}
*pbValue = pstJsonItem->unData.lValue > 0 ? 1 : 0;
return JSON_SUCCESS;
}
int vtoy_json_get_string
(
VTOY_JSON *pstJson,
const char *szKey,
uint32_t uiBufLen,
char *pcBuf
)
{
VTOY_JSON *pstJsonItem = NULL;
pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_STRING, szKey);
if (NULL == pstJsonItem)
{
//vdebug("Key %s is not found in json data.\n", szKey);
return JSON_NOT_FOUND;
}
scnprintf(pcBuf, uiBufLen, "%s", pstJsonItem->unData.pcStrVal);
return JSON_SUCCESS;
}
const char * vtoy_json_get_string_ex(VTOY_JSON *pstJson, const char *szKey)
{
VTOY_JSON *pstJsonItem = NULL;
if ((NULL == pstJson) || (NULL == szKey))
{
return NULL;
}
pstJsonItem = vtoy_json_find_item(pstJson, JSON_TYPE_STRING, szKey);
if (NULL == pstJsonItem)
{
//vdebug("Key %s is not found in json data.\n", szKey);
return NULL;
}
return pstJsonItem->unData.pcStrVal;
}
int vtoy_json_destroy(VTOY_JSON *pstJson)
{
if (NULL == pstJson)
{
return JSON_SUCCESS;
}
if (NULL != pstJson->pstChild)
{
vtoy_json_free(pstJson->pstChild);
}
if (NULL != pstJson->pstNext)
{
vtoy_json_free(pstJson->pstNext);
}
free(pstJson);
return JSON_SUCCESS;
}
int vtoy_json_escape_string(char *buf, int buflen, const char *str, int newline)
{
char last = 0;
int count = 0;
*buf++ = '"';
count++;
while (*str)
{
if (*str == '"' && last != '\\')
{
*buf = '\\';
count++;
buf++;
}
*buf = *str;
count++;
buf++;
last = *str;
str++;
}
*buf++ = '"';
count++;
*buf++ = ',';
count++;
if (newline)
{
*buf++ = '\n';
count++;
}
return count;
}

View File

@@ -0,0 +1,436 @@
/******************************************************************************
* ventoy_json.h
*
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __VENTOY_JSON_H__
#define __VENTOY_JSON_H__
#define JSON_NEW_ITEM(pstJson, ret) \
{ \
(pstJson) = (VTOY_JSON *)zalloc(sizeof(VTOY_JSON)); \
if (NULL == (pstJson)) \
{ \
vdebug("Failed to alloc memory for json."); \
return (ret); \
} \
}
#if defined(_MSC_VER) || defined(WIN32)
#define ssprintf(curpos, buf, len, fmt, ...) \
curpos += scnprintf(buf + curpos, len - curpos, fmt, ##__VA_ARGS__)
#define VTOY_JSON_IS_SKIPABLE(c) (((c) <= 32) ? 1 : 0)
#define VTOY_JSON_PRINT_PREFIX(uiDepth, ...) \
{ \
uint32_t _uiLoop = 0; \
for (_uiLoop = 0; _uiLoop < (uiDepth); _uiLoop++) \
{ \
ssprintf(uiCurPos, pcBuf, uiBufLen, " "); \
} \
ssprintf(uiCurPos, pcBuf, uiBufLen, ##__VA_ARGS__); \
}
#else
#define ssprintf(curpos, buf, len, fmt, args...) \
curpos += scnprintf(buf + curpos, len - curpos, fmt, ##args)
#define VTOY_JSON_IS_SKIPABLE(c) (((c) <= 32) ? 1 : 0)
#define VTOY_JSON_PRINT_PREFIX(uiDepth, args...) \
{ \
uint32_t _uiLoop = 0; \
for (_uiLoop = 0; _uiLoop < (uiDepth); _uiLoop++) \
{ \
ssprintf(uiCurPos, pcBuf, uiBufLen, " "); \
} \
ssprintf(uiCurPos, pcBuf, uiBufLen, ##args); \
}
#endif
#define VTOY_JSON_SUCCESS_RET "{ \"result\" : \"success\" }"
#define VTOY_JSON_FAILED_RET "{ \"result\" : \"failed\" }"
#define VTOY_JSON_INVALID_RET "{ \"result\" : \"invalidfmt\" }"
#define VTOY_JSON_TOKEN_ERR_RET "{ \"result\" : \"tokenerror\" }"
#define VTOY_JSON_EXIST_RET "{ \"result\" : \"exist\" }"
#define VTOY_JSON_TIMEOUT_RET "{ \"result\" : \"timeout\" }"
#define VTOY_JSON_BUSY_RET "{ \"result\" : \"busy\" }"
#define VTOY_JSON_INUSE_RET "{ \"result\" : \"inuse\" }"
#define VTOY_JSON_NOTFOUND_RET "{ \"result\" : \"notfound\" }"
#define VTOY_JSON_NOTRUNNING_RET "{ \"result\" : \"notrunning\" }"
#define VTOY_JSON_NOT_READY_RET "{ \"result\" : \"notready\" }"
#define VTOY_JSON_NOT_SUPPORT_RET "{ \"result\" : \"notsupport\" }"
#define VTOY_JSON_MBR_2TB_RET "{ \"result\" : \"mbr2tb\" }"
#define VTOY_JSON_INVALID_RSV_RET "{ \"result\" : \"reserve_invalid\" }"
#define VTOY_JSON_FILE_NOT_FOUND_RET "{ \"result\" : \"file_not_found\" }"
typedef enum tagJSON_TYPE
{
JSON_TYPE_NUMBER = 0,
JSON_TYPE_STRING,
JSON_TYPE_BOOL,
JSON_TYPE_ARRAY,
JSON_TYPE_OBJECT,
JSON_TYPE_NULL,
JSON_TYPE_BUTT
}JSON_TYPE;
typedef struct tagVTOY_JSON
{
struct tagVTOY_JSON *pstPrev;
struct tagVTOY_JSON *pstNext;
struct tagVTOY_JSON *pstChild;
JSON_TYPE enDataType;
union
{
char *pcStrVal;
int iNumVal;
uint64_t lValue;
}unData;
char *pcName;
}VTOY_JSON;
#define VTOY_JSON_FMT_BEGIN(uiCurPos, pcBuf, uiBufLen) \
{\
uint32_t __uiCurPos = (uiCurPos);\
uint32_t __uiBufLen = (uiBufLen);\
char *__pcBuf = (pcBuf);
#define VTOY_JSON_FMT_END(uiCurPos) \
(uiCurPos) = __uiCurPos;\
}
#define VTOY_JSON_FMT_OBJ_BEGIN() ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "{")
#define VTOY_JSON_FMT_OBJ_BEGIN_L(P) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s{", P)
#define VTOY_JSON_FMT_OBJ_BEGIN_N() ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "{\n")
#define VTOY_JSON_FMT_OBJ_BEGIN_LN(P) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s{\n", P)
#define VTOY_JSON_FMT_OBJ_END() \
{\
if (',' == *(__pcBuf + (__uiCurPos - 1)))\
{\
__uiCurPos -= 1;\
}\
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "}");\
}
#define VTOY_JSON_FMT_OBJ_ENDEX() \
{\
if (',' == *(__pcBuf + (__uiCurPos - 1)))\
{\
__uiCurPos -= 1;\
}\
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "},");\
}
#define VTOY_JSON_FMT_KEY(Key) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "\"%s\":", (Key))
#define VTOY_JSON_FMT_KEY_L(P, Key) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s\"%s\":", P, (Key))
#define VTOY_JSON_FMT_ITEM(Item) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "\"%s\",", (Item))
#define VTOY_JSON_FMT_ITEM_L(P, Item) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s\"%s\",", P, (Item))
#define VTOY_JSON_FMT_ITEM_LN(P, Item) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s\"%s\",\n", P, (Item))
#define VTOY_JSON_FMT_ITEM_PATH_LN(P, Item) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s\"%s\",\n", P, ventoy_real_path(Item))
#define VTOY_JSON_FMT_COMA() ssprintf(__uiCurPos, __pcBuf, __uiBufLen, ",")
#define VTOY_JSON_FMT_COMA_N(cnt) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, ",\n")
#define VTOY_JSON_FMT_COMA_N_CNT(cnt) if ((cnt) > 0) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, ",\n")
#define VTOY_JSON_FMT_APPEND_BEGIN() \
{ \
if ('}' == *(__pcBuf + (__uiCurPos - 1)))\
{\
__uiCurPos -= 1;\
}\
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, ",");\
}
#define VTOY_JSON_FMT_APPEND_END() \
{ \
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "}");\
}
#define VTOY_JSON_FMT_ARY_BEGIN() ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "[")
#define VTOY_JSON_FMT_ARY_BEGIN_N() ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "[\n")
#define VTOY_JSON_FMT_ARY_END() \
{\
if (',' == *(__pcBuf + (__uiCurPos - 1)))\
{\
__uiCurPos -= 1;\
}\
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "]");\
}
#define VTOY_JSON_FMT_ARY_ENDEX() \
{\
if (',' == *(__pcBuf + (__uiCurPos - 1)))\
{\
__uiCurPos -= 1;\
}\
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "],");\
}
#define VTOY_JSON_FMT_OBJ_END_L(P) \
{\
if ('\n' == *(__pcBuf + (__uiCurPos - 1)) && ',' == *(__pcBuf + (__uiCurPos - 2)))\
{\
*(__pcBuf + (__uiCurPos - 2)) = '\n';\
__uiCurPos -= 1;\
}\
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s}%s", P);\
}
#define VTOY_JSON_FMT_OBJ_ENDEX_L(P) \
{\
if ('\n' == *(__pcBuf + (__uiCurPos - 1)) && ',' == *(__pcBuf + (__uiCurPos - 2)))\
{\
*(__pcBuf + (__uiCurPos - 2)) = '\n';\
__uiCurPos -= 1;\
}\
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s},%s", P);\
}
#define VTOY_JSON_FMT_OBJ_END_LN(P) \
{\
if ('\n' == *(__pcBuf + (__uiCurPos - 1)) && ',' == *(__pcBuf + (__uiCurPos - 2)))\
{\
*(__pcBuf + (__uiCurPos - 2)) = '\n';\
__uiCurPos -= 1;\
}\
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s}\n", P);\
}
#define VTOY_JSON_FMT_OBJ_ENDEX_LN(P) \
{\
if ('\n' == *(__pcBuf + (__uiCurPos - 1)) && ',' == *(__pcBuf + (__uiCurPos - 2)))\
{\
*(__pcBuf + (__uiCurPos - 2)) = '\n';\
__uiCurPos -= 1;\
}\
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s},\n", P);\
}
#define VTOY_JSON_FMT_ARY_END_L(P) \
{\
if ('\n' == *(__pcBuf + (__uiCurPos - 1)) && ',' == *(__pcBuf + (__uiCurPos - 2)))\
{\
*(__pcBuf + (__uiCurPos - 2)) = '\n';\
__uiCurPos -= 1;\
}\
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s]", P);\
}
#define VTOY_JSON_FMT_ARY_END_LN(P) \
{\
if ('\n' == *(__pcBuf + (__uiCurPos - 1)) && ',' == *(__pcBuf + (__uiCurPos - 2)))\
{\
*(__pcBuf + (__uiCurPos - 2)) = '\n';\
__uiCurPos -= 1;\
}\
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s]\n", P);\
}
#define VTOY_JSON_FMT_ARY_ENDEX_L(P) \
{\
if ('\n' == *(__pcBuf + (__uiCurPos - 1)) && ',' == *(__pcBuf + (__uiCurPos - 2)))\
{\
*(__pcBuf + (__uiCurPos - 2)) = '\n';\
__uiCurPos -= 1;\
}\
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s],", P);\
}
#define VTOY_JSON_FMT_ARY_ENDEX_LN(P) \
{\
if ('\n' == *(__pcBuf + (__uiCurPos - 1)) && ',' == *(__pcBuf + (__uiCurPos - 2)))\
{\
*(__pcBuf + (__uiCurPos - 2)) = '\n';\
__uiCurPos -= 1;\
}\
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s],\n", P);\
}
#define VTOY_JSON_FMT_UINT64(Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "\"%s\": %llu,", Key, (_ull)Val)
#define VTOY_JSON_FMT_ULONG(Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "\"%s\": %lu,", Key, Val)
#define VTOY_JSON_FMT_LONG(Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "\"%s\": %ld,", Key, Val)
#define VTOY_JSON_FMT_UINT(Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "\"%s\": %u,", Key, Val)
#define VTOY_JSON_FMT_UINT_N(Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "\"%s\": %u,\n", Key, Val)
#define VTOY_JSON_FMT_UINT_L(P, Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s\"%s\": %u,", P, Key, Val)
#define VTOY_JSON_FMT_UINT_LN(P, Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s\"%s\": %u,\n", P, Key, Val)
#define VTOY_JSON_FMT_STRUINT(Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "\"%s\": \"%u\",", Key, Val)
#define VTOY_JSON_FMT_STRUINT_N(Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "\"%s\": \"%u\",\n", Key, Val)
#define VTOY_JSON_FMT_STRUINT_L(P, Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s\"%s\": \"%u\",", P, Key, Val)
#define VTOY_JSON_FMT_STRUINT_LN(P, Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s\"%s\": \"%u\",\n", P, Key, Val)
#define VTOY_JSON_FMT_STRSINT(Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "\"%s\": \"%d\",", Key, Val)
#define VTOY_JSON_FMT_STRSINT_N(Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "\"%s\": \"%d\",\n", Key, Val)
#define VTOY_JSON_FMT_STRSINT_L(P, Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s\"%s\": \"%d\",", P, Key, Val)
#define VTOY_JSON_FMT_STRSINT_LN(P, Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s\"%s\": \"%d\",\n", P, Key, Val)
#define VTOY_JSON_FMT_CTRL_INT(Prefix, Key, Field) \
if (def->Field != data->Field) \
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s{ \"%s\": \"%d\" },\n", Prefix, Key, data->Field)
#define VTOY_JSON_FMT_CTRL_STRN(P, Key, Field) \
if (strcmp(def->Field, data->Field)) \
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s{ \"%s\": \"%s\" },\n", P, Key, data->Field)
#define VTOY_JSON_FMT_CTRL_STRN_STR(P, Key, ptr) \
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s{ \"%s\": \"%s\" },\n", P, Key, ptr)
#define VTOY_JSON_FMT_CTRL_PUB_STRN(P, Key, Field) \
if (strcmp(def->Field, g_pub_path)) \
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s{ \"%s\": \"%s\" },\n", P, Key, g_pub_path)
#define VTOY_JSON_FMT_DIFF_STRN(P, Key, Field) \
if (strcmp(def->Field, data->Field)) \
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s\"%s\": \"%s\",\n", P, Key, data->Field)
#define VTOY_JSON_FMT_STRINT64(Key, Val) \
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "\"%s\": \"%llu\",", Key, Val)
#define VTOY_JSON_FMT_SINT(Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "\"%s\": %d,", Key, Val)
#define VTOY_JSON_FMT_SINT_N(Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "\"%s\": %d,\n", Key, Val)
#define VTOY_JSON_FMT_SINT_L(P, Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s\"%s\": %d,", P, Key, Val)
#define VTOY_JSON_FMT_SINT_LN(P, Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s\"%s\": %d,\n", P, Key, Val)
#define VTOY_JSON_FMT_DUBL(Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "\"%s\": %.1lf,", Key, Val)
#define VTOY_JSON_FMT_DUBL2(Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "\"%s\": %10.02lf,", Key, Val)
#define VTOY_JSON_FMT_STRN(Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "\"%s\": \"%s\",", Key, Val)
#define VTOY_JSON_FMT_STRN_N(Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "\"%s\": \"%s\",\n", Key, Val)
#define VTOY_JSON_FMT_STRN_L(P, Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s\"%s\": \"%s\",", P, Key, Val)
#define VTOY_JSON_FMT_STRN_LN(P, Key, Val) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s\"%s\": \"%s\",\n", P, Key, Val)
#define VTOY_JSON_FMT_STRN_PATH_LN(P, Key, Val) \
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s\"%s\": \"%s\",\n", P, Key, ventoy_real_path(Val))
int vtoy_json_escape_string(char *buf, int buflen, const char *str, int newline);
#define VTOY_JSON_FMT_STRN_EX_LN(P, Key, Val) \
{\
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "%s\"%s\": ", P, Key);\
__uiCurPos += vtoy_json_escape_string(__pcBuf + __uiCurPos, __uiBufLen - __uiCurPos, Val, 1);\
}
#define VTOY_JSON_FMT_NULL(Key) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "\"%s\": null,", Key)
#define VTOY_JSON_FMT_TRUE(Key) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "\"%s\": true,", (Key))
#define VTOY_JSON_FMT_FALSE(Key) ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "\"%s\": false,", (Key))
#define VTOY_JSON_FMT_BOOL(Key, Val) \
{\
if (0 == (Val))\
{\
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "\"%s\": false,", (Key));\
}\
else \
{\
ssprintf(__uiCurPos, __pcBuf, __uiBufLen, "\"%s\": true,", (Key));\
}\
}
typedef struct tagVTOY_JSON_PARSE
{
char *pcKey;
void *pDataBuf;
uint32_t uiBufSize;
}VTOY_JSON_PARSE_S;
#define JSON_SUCCESS 0
#define JSON_FAILED 1
#define JSON_NOT_FOUND 2
int vtoy_json_parse_value
(
char *pcNewStart,
char *pcRawStart,
VTOY_JSON *pstJson,
const char *pcData,
const char **ppcEnd
);
VTOY_JSON * vtoy_json_create(void);
int vtoy_json_parse(VTOY_JSON *pstJson, const char *szJsonData);
int vtoy_json_parse_ex(VTOY_JSON *pstJson, const char *szJsonData, int szLen);
int vtoy_json_destroy(VTOY_JSON *pstJson);
VTOY_JSON *vtoy_json_find_item
(
VTOY_JSON *pstJson,
JSON_TYPE enDataType,
const char *szKey
);
int vtoy_json_scan_parse
(
const VTOY_JSON *pstJson,
uint32_t uiParseNum,
VTOY_JSON_PARSE_S *pstJsonParse
);
int vtoy_json_get_int
(
VTOY_JSON *pstJson,
const char *szKey,
int *piValue
);
int vtoy_json_get_uint
(
VTOY_JSON *pstJson,
const char *szKey,
uint32_t *puiValue
);
int vtoy_json_get_uint64
(
VTOY_JSON *pstJson,
const char *szKey,
uint64_t *pui64Value
);
int vtoy_json_get_bool
(
VTOY_JSON *pstJson,
const char *szKey,
uint8_t *pbValue
);
int vtoy_json_get_string
(
VTOY_JSON *pstJson,
const char *szKey,
uint32_t uiBufLen,
char *pcBuf
);
const char * vtoy_json_get_string_ex(VTOY_JSON *pstJson, const char *szKey);
#endif /* __VENTOY_JSON_H__ */

View File

@@ -0,0 +1,151 @@
/******************************************************************************
* ventoy_log.c ---- ventoy log
*
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <ventoy_define.h>
#include <ventoy_util.h>
extern char g_log_file[MAX_PATH];
static int g_ventoy_log_level = VLOG_DEBUG;
static pthread_mutex_t g_log_mutex;
int ventoy_log_init(void)
{
if (ventoy_get_file_size(g_log_file) >= SIZE_1MB)
{
#if defined(_MSC_VER) || defined(WIN32)
DeleteFileA(g_log_file);
#else
remove(g_log_file);
#endif
}
pthread_mutex_init(&g_log_mutex, NULL);
return 0;
}
void ventoy_log_exit(void)
{
pthread_mutex_destroy(&g_log_mutex);
}
void ventoy_set_loglevel(int level)
{
g_ventoy_log_level = level;
}
void ventoy_syslog_printf(const char *Fmt, ...)
{
char log[512];
va_list arg;
time_t stamp;
struct tm ttm;
FILE *fp;
time(&stamp);
localtime_r(&stamp, &ttm);
va_start(arg, Fmt);
#if defined(_MSC_VER) || defined(WIN32)
vsnprintf_s(log, 512, _TRUNCATE, Fmt, arg);
#else
vsnprintf(log, 512, Fmt, arg);
#endif
va_end(arg);
pthread_mutex_lock(&g_log_mutex);
#if defined(_MSC_VER) || defined(WIN32)
fopen_s(&fp, g_log_file, "a+");
#else
fp = fopen(g_log_file, "a+");
#endif
if (fp)
{
fprintf(fp, "[%04u/%02u/%02u %02u:%02u:%02u] %s",
ttm.tm_year, ttm.tm_mon + 1, ttm.tm_mday,
ttm.tm_hour, ttm.tm_min, ttm.tm_sec,
log);
fclose(fp);
#ifdef VENTOY_SIM
printf("[%04u/%02u/%02u %02u:%02u:%02u] %s",
ttm.tm_year, ttm.tm_mon + 1, ttm.tm_mday,
ttm.tm_hour, ttm.tm_min, ttm.tm_sec,
log);
#endif
}
pthread_mutex_unlock(&g_log_mutex);
}
void ventoy_syslog(int level, const char *Fmt, ...)
{
char log[512];
va_list arg;
time_t stamp;
struct tm ttm;
FILE *fp;
if (level > g_ventoy_log_level)
{
return;
}
time(&stamp);
localtime_r(&stamp, &ttm);
va_start(arg, Fmt);
#if defined(_MSC_VER) || defined(WIN32)
vsnprintf_s(log, 512, _TRUNCATE, Fmt, arg);
#else
vsnprintf(log, 512, Fmt, arg);
#endif
va_end(arg);
pthread_mutex_lock(&g_log_mutex);
#if defined(_MSC_VER) || defined(WIN32)
fopen_s(&fp, g_log_file, "a+");
#else
fp = fopen(g_log_file, "a+");
#endif
if (fp)
{
fprintf(fp, "[%04u/%02u/%02u %02u:%02u:%02u] %s",
ttm.tm_year + 1900, ttm.tm_mon + 1, ttm.tm_mday,
ttm.tm_hour, ttm.tm_min, ttm.tm_sec,
log);
fclose(fp);
#ifdef VENTOY_SIM
printf("[%04u/%02u/%02u %02u:%02u:%02u] %s",
ttm.tm_year + 1900, ttm.tm_mon + 1, ttm.tm_mday,
ttm.tm_hour, ttm.tm_min, ttm.tm_sec,
log);
#endif
}
pthread_mutex_unlock(&g_log_mutex);
}

View File

@@ -0,0 +1,166 @@
/******************************************************************************
* ventoy_md5.c ---- ventoy md5
*
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
const static uint32_t k[64] =
{
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
};
const static uint32_t r[] =
{
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
};
#define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
#define to_bytes(val, bytes) *((uint32_t *)(bytes)) = (val)
#define ROTATE_CALC() \
{\
temp = d; \
d = c; \
c = b; \
b = b + LEFTROTATE((a + f + k[i] + w[g]), r[i]); \
a = temp; \
}
void ventoy_md5(const void *data, uint32_t len, uint8_t *md5)
{
uint32_t h0, h1, h2, h3;
uint32_t w[16];
uint32_t a, b, c, d, i, f, g, temp;
uint32_t offset, mod, delta;
uint8_t postbuf[128] = {0};
// Initialize variables - simple count in nibbles:
h0 = 0x67452301;
h1 = 0xefcdab89;
h2 = 0x98badcfe;
h3 = 0x10325476;
//Pre-processing:
//append "1" bit to message
//append "0" bits until message length in bits <20><> 448 (mod 512)
//append length mod (2^64) to message
mod = len % 64;
if (mod)
{
memcpy(postbuf, (const uint8_t *)data + len - mod, mod);
}
postbuf[mod] = 0x80;
if (mod < 56)
{
to_bytes(len * 8, postbuf + 56);
to_bytes(len >> 29, postbuf + 60);
delta = 64;
}
else
{
to_bytes(len * 8, postbuf + 120);
to_bytes(len >> 29, postbuf + 124);
delta = 128;
}
len -= mod;
for (offset = 0; offset < len + delta; offset += 64)
{
if (offset < len)
{
memcpy(w, (const uint8_t *)data + offset, 64);
}
else
{
memcpy(w, postbuf + offset - len, 64);
}
// Initialize hash value for this chunk:
a = h0;
b = h1;
c = h2;
d = h3;
// Main loop:
for (i = 0; i < 16; i++)
{
f = (b & c) | ((~b) & d);
g = i;
ROTATE_CALC();
}
for (i = 16; i < 32; i++)
{
f = (d & b) | ((~d) & c);
g = (5 * i + 1) % 16;
ROTATE_CALC();
}
for (i = 32; i < 48; i++)
{
f = b ^ c ^ d;
g = (3 * i + 5) % 16;
ROTATE_CALC();
}
for (i = 48; i < 64; i++)
{
f = c ^ (b | (~d));
g = (7 * i) % 16;
ROTATE_CALC();
}
// Add this chunk's hash to result so far:
h0 += a;
h1 += b;
h2 += c;
h3 += d;
}
//var char md5[16] := h0 append h1 append h2 append h3 //(Output is in little-endian)
to_bytes(h0, md5);
to_bytes(h1, md5 + 4);
to_bytes(h2, md5 + 8);
to_bytes(h3, md5 + 12);
}

View File

@@ -0,0 +1,260 @@
/******************************************************************************
* ventoy_util.c ---- ventoy util
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <ventoy_define.h>
#include <ventoy_util.h>
static int g_tar_filenum = 0;
static char *g_tar_buffer = NULL;
static ventoy_file *g_tar_filelist = NULL;
SYSINFO g_sysinfo;
unsigned char *g_unxz_buffer = NULL;
int g_unxz_len = 0;
void unxz_error(char *x)
{
vlog("%s\n", x);
}
int unxz_flush(void *src, unsigned int size)
{
memcpy(g_unxz_buffer + g_unxz_len, src, size);
g_unxz_len += (int)size;
return (int)size;
}
uint64_t ventoy_get_human_readable_gb(uint64_t SizeBytes)
{
int i;
int Pow2 = 1;
double Delta;
double GB = SizeBytes * 1.0 / 1000 / 1000 / 1000;
if ((SizeBytes % SIZE_1GB) == 0)
{
return (uint64_t)(SizeBytes / SIZE_1GB);
}
for (i = 0; i < 12; i++)
{
if (Pow2 > GB)
{
Delta = (Pow2 - GB) / Pow2;
}
else
{
Delta = (GB - Pow2) / Pow2;
}
if (Delta < 0.05)
{
return Pow2;
}
Pow2 <<= 1;
}
return (uint64_t)GB;
}
ventoy_file * ventoy_tar_find_file(const char *path)
{
int i;
int len;
ventoy_file *node = g_tar_filelist;
len = (int)strlen(path);
for (i = 0; i < g_tar_filenum; i++, node++)
{
if (node->pathlen == len && memcmp(node->path, path, len) == 0)
{
return node;
}
if (node->pathlen > len)
{
break;
}
}
return NULL;
}
int ventoy_decompress_tar(char *tarbuf, int buflen, int *tarsize)
{
int rc = 1;
int inused = 0;
int BufLen = 0;
unsigned char *buffer = NULL;
char tarxz[MAX_PATH];
#if defined(_MSC_VER) || defined(WIN32)
scnprintf(tarxz, sizeof(tarxz), "%s\\ventoy\\%s", g_ventoy_dir, PLUGSON_TXZ);
#else
scnprintf(tarxz, sizeof(tarxz), "%s/tool/%s", g_ventoy_dir, PLUGSON_TXZ);
#endif
if (ventoy_read_file_to_buf(tarxz, 0, (void **)&buffer, &BufLen))
{
vlog("Failed to read file <%s>\n", tarxz);
return 1;
}
g_unxz_buffer = (unsigned char *)tarbuf;
g_unxz_len = 0;
unxz(buffer, BufLen, NULL, unxz_flush, NULL, &inused, unxz_error);
vlog("xzlen:%u rawdata size:%d\n", BufLen, g_unxz_len);
if (inused != BufLen)
{
vlog("Failed to unxz data %d %d\n", inused, BufLen);
rc = 1;
}
else
{
*tarsize = g_unxz_len;
rc = 0;
}
free(buffer);
return rc;
}
int ventoy_www_init(void)
{
int i = 0;
int j = 0;
int size = 0;
int tarsize = 0;
int offset = 0;
ventoy_file *node = NULL;
ventoy_file *node2 = NULL;
VENTOY_TAR_HEAD *pHead = NULL;
ventoy_file tmpnode;
if (!g_tar_filelist)
{
g_tar_filelist = malloc(VENTOY_FILE_MAX * sizeof(ventoy_file));
g_tar_buffer = malloc(TAR_BUF_MAX);
g_tar_filenum = 0;
}
if ((!g_tar_filelist) || (!g_tar_buffer))
{
return 1;
}
if (ventoy_decompress_tar(g_tar_buffer, TAR_BUF_MAX, &tarsize))
{
vlog("Failed to decompress tar\n");
return 1;
}
pHead = (VENTOY_TAR_HEAD *)g_tar_buffer;
node = g_tar_filelist;
while (g_tar_filenum < VENTOY_FILE_MAX && size < tarsize && memcmp(pHead->magic, TMAGIC, 5) == 0)
{
if (pHead->typeflag == REGTYPE)
{
node->size = (int)strtol(pHead->size, NULL, 8);
node->pathlen = (int)scnprintf(node->path, MAX_PATH, "%s", pHead->name);
node->addr = pHead + 1;
if (node->pathlen == 13 && strcmp(pHead->name, "www/buildtime") == 0)
{
scnprintf(g_sysinfo.buildtime, sizeof(g_sysinfo.buildtime), "%s", (char *)node->addr);
vlog("Plugson buildtime %s\n", g_sysinfo.buildtime);
}
offset = 512 + VENTOY_UP_ALIGN(node->size, 512);
node++;
g_tar_filenum++;
}
else
{
offset = 512;
}
pHead = (VENTOY_TAR_HEAD *)((char *)pHead + offset);
size += offset;
}
//sort
for (i = 0; i < g_tar_filenum; i++)
for (j = i + 1; j < g_tar_filenum; j++)
{
node = g_tar_filelist + i;
node2 = g_tar_filelist + j;
if (node->pathlen > node2->pathlen)
{
memcpy(&tmpnode, node, sizeof(ventoy_file));
memcpy(node, node2, sizeof(ventoy_file));
memcpy(node2, &tmpnode, sizeof(ventoy_file));
}
}
vlog("Total extract %d files from tar file.\n", g_tar_filenum);
return 0;
}
void ventoy_www_exit(void)
{
check_free(g_tar_filelist);
check_free(g_tar_buffer);
g_tar_filelist = NULL;
g_tar_buffer = NULL;
g_tar_filenum = 0;
}
void ventoy_get_json_path(char *path, char *backup)
{
#if defined(_MSC_VER) || defined(WIN32)
scnprintf(path, 64, "%C:\\ventoy\\ventoy.json", g_cur_dir[0]);
if (backup)
{
scnprintf(backup, 64, "%C:\\ventoy\\ventoy_backup.json", g_cur_dir[0]);
}
#else
scnprintf(path, 64, "%s/ventoy/ventoy.json", g_cur_dir);
if (backup)
{
scnprintf(backup, 64, "%s/ventoy/ventoy_backup.json", g_cur_dir);
}
#endif
}

View File

@@ -0,0 +1,202 @@
/******************************************************************************
* ventoy_util.h
*
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __VENTOY_UTIL_H__
#define __VENTOY_UTIL_H__
#define PLUGSON_TXZ "plugson.tar.xz"
#define check_free(p) if (p) free(p)
#define vtoy_safe_close_fd(fd) \
{\
if ((fd) >= 0) \
{ \
close(fd); \
(fd) = -1; \
}\
}
extern char g_cur_dir[MAX_PATH];
extern char g_ventoy_dir[MAX_PATH];
#if defined(_MSC_VER) || defined(WIN32)
typedef HANDLE pthread_mutex_t;
static __inline int pthread_mutex_init(pthread_mutex_t *mutex, void *unused)
{
(void)unused;
*mutex = CreateMutex(NULL, FALSE, NULL);
return *mutex == NULL ? -1 : 0;
}
static __inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
{
return CloseHandle(*mutex) == 0 ? -1 : 0;
}
static __inline int pthread_mutex_unlock(pthread_mutex_t *mutex)
{
return ReleaseMutex(*mutex) == 0 ? -1 : 0;
}
static __inline int pthread_mutex_lock(pthread_mutex_t *mutex)
{
return WaitForSingleObject(*mutex, INFINITE) == WAIT_OBJECT_0 ? 0 : -1;
}
int ventoy_path_case(char *path, int slash);
#else
int ventoy_get_sys_file_line(char *buffer, int buflen, const char *fmt, ...);
#define UINT8 uint8_t
#define UINT16 uint16_t
#define UINT32 uint32_t
#define UINT64 uint64_t
static inline int ventoy_path_case(char *path, int slash)
{
(void)path;
(void)slash;
return 0;
}
#endif
#define LANGUAGE_EN 0
#define LANGUAGE_CN 1
typedef struct SYSINFO
{
char buildtime[128];
int syntax_error;
int language;
int pathcase;
char cur_fsname[64];
char cur_capacity[64];
char cur_model[256];
char cur_ventoy_ver[64];
int cur_secureboot;
int cur_part_style;
char ip[32];
char port[16];
}SYSINFO;
extern SYSINFO g_sysinfo;
#define TMAGIC "ustar"
#define REGTYPE '0'
#define AREGTYPE '\0'
#define LNKTYPE '1'
#define CHRTYPE '3'
#define BLKTYPE '4'
#define DIRTYPE '5'
#define FIFOTYPE '6'
#define CONTTYPE '7'
#pragma pack(1)
typedef struct tag_tar_head
{
char name[100];
char mode[8];
char uid[8];
char gid[8];
char size[12];
char mtime[12];
char chksum[8];
char typeflag;
char linkname[100];
char magic[6];
char version[2];
char uname[32];
char gname[32];
char devmajor[8];
char devminor[8];
char prefix[155];
char padding[12];
}VENTOY_TAR_HEAD;
#pragma pack()
#define VENTOY_UP_ALIGN(N, align) (((N) + ((align) - 1)) / (align) * (align))
#define VENTOY_FILE_MAX 2048
#if defined(_MSC_VER) || defined(WIN32)
#define million_sleep(a) Sleep(a)
#else
#define million_sleep(a) usleep((a) * 1000)
#endif
typedef struct ventoy_file
{
int size;
char path[MAX_PATH];
int pathlen;
void *addr;
}ventoy_file;
int ventoy_is_file_exist(const char *fmt, ...);
int ventoy_is_directory_exist(const char *fmt, ...);
void ventoy_gen_preudo_uuid(void *uuid);
uint64_t ventoy_get_human_readable_gb(uint64_t SizeBytes);
void ventoy_md5(const void *data, uint32_t len, uint8_t *md5);
int ventoy_is_disk_mounted(const char *devpath);
int unxz(unsigned char *in, int in_size,
int (*fill)(void *dest, unsigned int size),
int (*flush)(void *src, unsigned int size),
unsigned char *out, int *in_used,
void (*error)(char *x));
int ventoy_read_file_to_buf(const char *FileName, int ExtLen, void **Bufer, int *BufLen);
int ventoy_write_buf_to_file(const char *FileName, void *Bufer, int BufLen);
const char * ventoy_get_os_language(void);
int ventoy_get_file_size(const char *file);
int ventoy_www_init(void);
void ventoy_www_exit(void);
int ventoy_decompress_tar(char *tarbuf, int buflen, int *tarsize);
ventoy_file * ventoy_tar_find_file(const char *path);
void ventoy_get_json_path(char *path, char *backup);
int ventoy_copy_file(const char *a, const char *b);
typedef int (*ventoy_http_writeback_pf)(void);
int ventoy_start_writeback_thread(ventoy_http_writeback_pf callback);
void ventoy_stop_writeback_thread(void);
void ventoy_set_writeback_event(void);
extern unsigned char *g_unxz_buffer;
extern int g_unxz_len;
void unxz_error(char *x);
int unxz_flush(void *src, unsigned int size);
#endif /* __VENTOY_UTIL_H__ */

View File

@@ -0,0 +1,343 @@
/******************************************************************************
* ventoy_util_linux.c ---- ventoy util
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mount.h>
#include <linux/fs.h>
#include <dirent.h>
#include <time.h>
#include <ventoy_define.h>
#include <ventoy_util.h>
void ventoy_gen_preudo_uuid(void *uuid)
{
int i;
int fd;
fd = open("/dev/urandom", O_RDONLY | O_BINARY);
if (fd < 0)
{
srand(time(NULL));
for (i = 0; i < 8; i++)
{
*((uint16_t *)uuid + i) = (uint16_t)(rand() & 0xFFFF);
}
}
else
{
read(fd, uuid, 16);
close(fd);
}
}
int ventoy_get_sys_file_line(char *buffer, int buflen, const char *fmt, ...)
{
int len;
char c;
char path[256];
va_list arg;
va_start(arg, fmt);
vsnprintf(path, 256, fmt, arg);
va_end(arg);
if (access(path, F_OK) >= 0)
{
FILE *fp = fopen(path, "r");
memset(buffer, 0, buflen);
len = (int)fread(buffer, 1, buflen - 1, fp);
fclose(fp);
while (len > 0)
{
c = buffer[len - 1];
if (c == '\r' || c == '\n' || c == ' ' || c == '\t')
{
buffer[len - 1] = 0;
len--;
}
else
{
break;
}
}
return 0;
}
else
{
vdebug("%s not exist \n", path);
return 1;
}
}
int ventoy_is_disk_mounted(const char *devpath)
{
int len;
int mount = 0;
char line[512];
FILE *fp = NULL;
fp = fopen("/proc/mounts", "r");
if (!fp)
{
return 0;
}
len = (int)strlen(devpath);
while (fgets(line, sizeof(line), fp))
{
if (strncmp(line, devpath, len) == 0)
{
mount = 1;
vdebug("%s mounted <%s>\n", devpath, line);
goto end;
}
}
end:
fclose(fp);
return mount;
}
const char * ventoy_get_os_language(void)
{
const char *env = getenv("LANG");
if (env && strncasecmp(env, "zh_CN", 5) == 0)
{
return "cn";
}
else
{
return "en";
}
}
int ventoy_is_file_exist(const char *fmt, ...)
{
va_list ap;
struct stat sb;
char fullpath[MAX_PATH];
va_start (ap, fmt);
vsnprintf(fullpath, MAX_PATH, fmt, ap);
va_end (ap);
if (stat(fullpath, &sb))
{
return 0;
}
if (S_ISREG(sb.st_mode))
{
return 1;
}
return 0;
}
int ventoy_is_directory_exist(const char *fmt, ...)
{
va_list ap;
struct stat sb;
char fullpath[MAX_PATH];
va_start (ap, fmt);
vsnprintf(fullpath, MAX_PATH, fmt, ap);
va_end (ap);
if (stat(fullpath, &sb))
{
return 0;
}
if (S_ISDIR(sb.st_mode))
{
return 1;
}
return 0;
}
int ventoy_get_file_size(const char *file)
{
int Size = -1;
struct stat stStat;
if (stat(file, &stStat) >= 0)
{
Size = (int)(stStat.st_size);
}
return Size;
}
int ventoy_write_buf_to_file(const char *FileName, void *Bufer, int BufLen)
{
int fd;
int rc;
ssize_t size;
fd = open(FileName, O_CREAT | O_RDWR | O_TRUNC, 0755);
if (fd < 0)
{
vlog("Failed to open file %s %d\n", FileName, errno);
return 1;
}
rc = fchmod(fd, 0755);
if (rc)
{
vlog("Failed to chmod <%s> %d\n", FileName, errno);
}
size = write(fd, Bufer, BufLen);
if ((int)size != BufLen)
{
close(fd);
vlog("write file %s failed %d err:%d\n", FileName, (int)size, errno);
return 1;
}
fsync(fd);
close(fd);
return 0;
}
static volatile int g_thread_stop = 0;
static pthread_t g_writeback_thread;
static pthread_mutex_t g_writeback_mutex;
static pthread_cond_t g_writeback_cond;
static void * ventoy_local_thread_run(void* data)
{
ventoy_http_writeback_pf callback = (ventoy_http_writeback_pf)data;
while (1)
{
pthread_mutex_lock(&g_writeback_mutex);
pthread_cond_wait(&g_writeback_cond, &g_writeback_mutex);
if (g_thread_stop)
{
pthread_mutex_unlock(&g_writeback_mutex);
break;
}
else
{
callback();
pthread_mutex_unlock(&g_writeback_mutex);
}
}
return NULL;
}
void ventoy_set_writeback_event(void)
{
pthread_cond_signal(&g_writeback_cond);
}
int ventoy_start_writeback_thread(ventoy_http_writeback_pf callback)
{
g_thread_stop = 0;
pthread_mutex_init(&g_writeback_mutex, NULL);
pthread_cond_init(&g_writeback_cond, NULL);
pthread_create(&g_writeback_thread, NULL, ventoy_local_thread_run, callback);
return 0;
}
void ventoy_stop_writeback_thread(void)
{
g_thread_stop = 1;
pthread_cond_signal(&g_writeback_cond);
pthread_join(g_writeback_thread, NULL);
pthread_cond_destroy(&g_writeback_cond);
pthread_mutex_destroy(&g_writeback_mutex);
}
int ventoy_read_file_to_buf(const char *FileName, int ExtLen, void **Bufer, int *BufLen)
{
int FileSize;
FILE *fp = NULL;
void *Data = NULL;
fp = fopen(FileName, "rb");
if (fp == NULL)
{
vlog("Failed to open file %s", FileName);
return 1;
}
fseek(fp, 0, SEEK_END);
FileSize = (int)ftell(fp);
Data = malloc(FileSize + ExtLen);
if (!Data)
{
fclose(fp);
return 1;
}
fseek(fp, 0, SEEK_SET);
fread(Data, 1, FileSize, fp);
fclose(fp);
*Bufer = Data;
*BufLen = FileSize;
return 0;
}
int ventoy_copy_file(const char *a, const char *b)
{
int len = 0;
char *buf = NULL;
if (0 == ventoy_read_file_to_buf(a, 0, (void **)&buf, &len))
{
ventoy_write_buf_to_file(b, buf, len);
free(buf);
}
return 0;
}

View File

@@ -0,0 +1,796 @@
/******************************************************************************
* ventoy_util.c ---- ventoy util
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <ventoy_define.h>
#include <ventoy_util.h>
#include <ventoy_disk.h>
#include "fat_filelib.h"
static void TrimString(CHAR *String)
{
CHAR *Pos1 = String;
CHAR *Pos2 = String;
size_t Len = strlen(String);
while (Len > 0)
{
if (String[Len - 1] != ' ' && String[Len - 1] != '\t')
{
break;
}
String[Len - 1] = 0;
Len--;
}
while (*Pos1 == ' ' || *Pos1 == '\t')
{
Pos1++;
}
while (*Pos1)
{
*Pos2++ = *Pos1++;
}
*Pos2++ = 0;
return;
}
void ventoy_gen_preudo_uuid(void *uuid)
{
CoCreateGuid((GUID *)uuid);
}
static int IsUTF8Encode(const char *src)
{
int i;
const UCHAR *Byte = (const UCHAR *)src;
for (i = 0; i < MAX_PATH && Byte[i]; i++)
{
if (Byte[i] > 127)
{
return 1;
}
}
return 0;
}
static int Utf8ToUtf16(const char* src, WCHAR * dst)
{
return MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, MAX_PATH * sizeof(WCHAR));
}
static int Utf16ToUtf8(const WCHAR* src, CHAR * dst)
{
int size = WideCharToMultiByte(CP_UTF8, 0, src, -1, dst, MAX_PATH, NULL, 0);
dst[size] = 0;
return size;
}
int ventoy_path_case(char *path, int slash)
{
int i;
int j = 0;
int count = 0;
int isUTF8 = 0;
BOOL bRet;
HANDLE handle = INVALID_HANDLE_VALUE;
WCHAR Buffer[MAX_PATH + 16];
WCHAR FilePathW[MAX_PATH];
CHAR FilePathA[MAX_PATH];
FILE_NAME_INFO *pInfo = NULL;
if (g_sysinfo.pathcase == 0)
{
return 0;
}
if (path == NULL || path[0] == '/' || path[0] == '\\')
{
return 0;
}
isUTF8 = IsUTF8Encode(path);
if (isUTF8)
{
Utf8ToUtf16(path, FilePathW);
handle = CreateFileW(FilePathW, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
}
else
{
handle = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
}
if (handle != INVALID_HANDLE_VALUE)
{
bRet = GetFileInformationByHandleEx(handle, FileNameInfo, Buffer, sizeof(Buffer));
if (bRet)
{
pInfo = (FILE_NAME_INFO *)Buffer;
if (slash)
{
for (i = 0; i < (int)(pInfo->FileNameLength / sizeof(WCHAR)); i++)
{
if (pInfo->FileName[i] == L'\\')
{
pInfo->FileName[i] = L'/';
}
}
}
pInfo->FileName[(pInfo->FileNameLength / sizeof(WCHAR))] = 0;
memset(FilePathA, 0, sizeof(FilePathA));
Utf16ToUtf8(pInfo->FileName, FilePathA);
if (FilePathA[1] == ':')
{
j = 3;
}
else
{
j = 1;
}
for (i = 0; i < MAX_PATH && j < MAX_PATH; i++, j++)
{
if (FilePathA[j] == 0)
{
break;
}
if (path[i] != FilePathA[j])
{
path[i] = FilePathA[j];
count++;
}
}
}
CHECK_CLOSE_HANDLE(handle);
}
return count;
}
int ventoy_is_directory_exist(const char *Fmt, ...)
{
va_list Arg;
DWORD Attr;
int UTF8 = 0;
CHAR FilePathA[MAX_PATH];
WCHAR FilePathW[MAX_PATH];
va_start(Arg, Fmt);
vsnprintf_s(FilePathA, sizeof(FilePathA), sizeof(FilePathA), Fmt, Arg);
va_end(Arg);
UTF8 = IsUTF8Encode(FilePathA);
if (UTF8)
{
Utf8ToUtf16(FilePathA, FilePathW);
Attr = GetFileAttributesW(FilePathW);
}
else
{
Attr = GetFileAttributesA(FilePathA);
}
if (Attr != INVALID_FILE_ATTRIBUTES && (Attr & FILE_ATTRIBUTE_DIRECTORY))
{
return TRUE;
}
return FALSE;
}
int ventoy_is_file_exist(const char *Fmt, ...)
{
va_list Arg;
HANDLE hFile;
DWORD Attr;
int UTF8 = 0;
CHAR FilePathA[MAX_PATH];
WCHAR FilePathW[MAX_PATH];
va_start(Arg, Fmt);
vsnprintf_s(FilePathA, sizeof(FilePathA), sizeof(FilePathA), Fmt, Arg);
va_end(Arg);
UTF8 = IsUTF8Encode(FilePathA);
if (UTF8)
{
Utf8ToUtf16(FilePathA, FilePathW);
hFile = CreateFileW(FilePathW, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
Attr = GetFileAttributesW(FilePathW);
}
else
{
hFile = CreateFileA(FilePathA, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
Attr = GetFileAttributesA(FilePathA);
}
if (INVALID_HANDLE_VALUE == hFile)
{
return 0;
}
CloseHandle(hFile);
if (Attr & FILE_ATTRIBUTE_DIRECTORY)
{
return 0;
}
return 1;
}
const char * ventoy_get_os_language(void)
{
if (GetUserDefaultUILanguage() == 0x0804)
{
return "cn";
}
else
{
return "en";
}
}
int GetPhyDriveByLogicalDrive(int DriveLetter, UINT64 *Offset)
{
BOOL Ret;
DWORD dwSize;
HANDLE Handle;
VOLUME_DISK_EXTENTS DiskExtents;
CHAR PhyPath[128];
scnprintf(PhyPath, sizeof(PhyPath), "\\\\.\\%C:", (CHAR)DriveLetter);
Handle = CreateFileA(PhyPath, 0, 0, 0, OPEN_EXISTING, 0, 0);
if (Handle == INVALID_HANDLE_VALUE)
{
vlog("CreateFileA %s failed %u\n", PhyPath, LASTERR);
return -1;
}
Ret = DeviceIoControl(Handle,
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
NULL,
0,
&DiskExtents,
(DWORD)(sizeof(DiskExtents)),
(LPDWORD)&dwSize,
NULL);
if (!Ret || DiskExtents.NumberOfDiskExtents == 0)
{
vlog("IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTSfailed %u\n", LASTERR);
CHECK_CLOSE_HANDLE(Handle);
return -1;
}
CHECK_CLOSE_HANDLE(Handle);
if (Offset)
{
*Offset = (UINT64)(DiskExtents.Extents[0].StartingOffset.QuadPart);
}
return (int)DiskExtents.Extents[0].DiskNumber;
}
int GetPhyDriveInfo(int PhyDrive, UINT64 *Size, CHAR *Vendor, CHAR *Product)
{
int ret = 1;
BOOL bRet;
DWORD dwBytes;
CHAR Drive[64];
HANDLE Handle = INVALID_HANDLE_VALUE;
GET_LENGTH_INFORMATION LengthInfo;
STORAGE_PROPERTY_QUERY Query;
STORAGE_DESCRIPTOR_HEADER DevDescHeader;
STORAGE_DEVICE_DESCRIPTOR *pDevDesc = NULL;
sprintf_s(Drive, sizeof(Drive), "\\\\.\\PhysicalDrive%d", PhyDrive);
Handle = CreateFileA(Drive, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (Handle == INVALID_HANDLE_VALUE)
{
vlog("CreateFileA %s failed %u\n", Drive, LASTERR);
goto out;
}
bRet = DeviceIoControl(Handle,
IOCTL_DISK_GET_LENGTH_INFO, NULL,
0,
&LengthInfo,
sizeof(LengthInfo),
&dwBytes,
NULL);
if (!bRet)
{
vlog("IOCTL_DISK_GET_LENGTH_INFO failed %u\n", LASTERR);
return 1;
}
if (Size)
{
*Size = (UINT64)LengthInfo.Length.QuadPart;
}
Query.PropertyId = StorageDeviceProperty;
Query.QueryType = PropertyStandardQuery;
bRet = DeviceIoControl(Handle,
IOCTL_STORAGE_QUERY_PROPERTY,
&Query,
sizeof(Query),
&DevDescHeader,
sizeof(STORAGE_DESCRIPTOR_HEADER),
&dwBytes,
NULL);
if (!bRet)
{
vlog("IOCTL_STORAGE_QUERY_PROPERTY failed %u\n", LASTERR);
goto out;
}
if (DevDescHeader.Size < sizeof(STORAGE_DEVICE_DESCRIPTOR))
{
vlog("DevDescHeader.size invalid %u\n", DevDescHeader.Size);
goto out;
}
pDevDesc = (STORAGE_DEVICE_DESCRIPTOR *)malloc(DevDescHeader.Size);
if (!pDevDesc)
{
vlog("malloc failed\n");
goto out;
}
bRet = DeviceIoControl(Handle,
IOCTL_STORAGE_QUERY_PROPERTY,
&Query,
sizeof(Query),
pDevDesc,
DevDescHeader.Size,
&dwBytes,
NULL);
if (!bRet)
{
vlog("IOCTL_STORAGE_QUERY_PROPERTY failed %u\n", LASTERR);
goto out;
}
if (pDevDesc->VendorIdOffset && Vendor)
{
strcpy_s(Vendor, 128, (char *)pDevDesc + pDevDesc->VendorIdOffset);
TrimString(Vendor);
}
if (pDevDesc->ProductIdOffset && Product)
{
strcpy_s(Product, 128, (char *)pDevDesc + pDevDesc->ProductIdOffset);
TrimString(Product);
}
ret = 0;
out:
CHECK_FREE(pDevDesc);
CHECK_CLOSE_HANDLE(Handle);
return ret;
}
int ventoy_get_file_size(const char *file)
{
int Size = -1;
HANDLE hFile;
hFile = CreateFileA(file, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
Size = (int)GetFileSize(hFile, NULL);
CHECK_CLOSE_HANDLE(hFile);
}
return Size;
}
static HANDLE g_FatPhyDrive;
static UINT64 g_Part2StartSec;
const CHAR* ParseVentoyVersionFromString(CHAR *Buf)
{
CHAR *Pos = NULL;
CHAR *End = NULL;
static CHAR LocalVersion[64] = { 0 };
Pos = strstr(Buf, "VENTOY_VERSION=");
if (Pos)
{
Pos += strlen("VENTOY_VERSION=");
if (*Pos == '"')
{
Pos++;
}
End = Pos;
while (*End != 0 && *End != '"' && *End != '\r' && *End != '\n')
{
End++;
}
*End = 0;
sprintf_s(LocalVersion, sizeof(LocalVersion), "%s", Pos);
return LocalVersion;
}
return "";
}
static int GetVentoyVersionFromFatFile(CHAR *VerBuf, size_t BufLen)
{
int rc = 1;
int size = 0;
char *buf = NULL;
void *flfile = NULL;
flfile = fl_fopen("/grub/grub.cfg", "rb");
if (flfile)
{
fl_fseek(flfile, 0, SEEK_END);
size = (int)fl_ftell(flfile);
fl_fseek(flfile, 0, SEEK_SET);
buf = (char *)malloc(size + 1);
if (buf)
{
fl_fread(buf, 1, size, flfile);
buf[size] = 0;
rc = 0;
sprintf_s(VerBuf, BufLen, "%s", ParseVentoyVersionFromString(buf));
free(buf);
}
fl_fclose(flfile);
}
return rc;
}
static int VentoyFatDiskRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
{
DWORD dwSize;
BOOL bRet;
DWORD ReadSize;
LARGE_INTEGER liCurrentPosition;
liCurrentPosition.QuadPart = Sector + g_Part2StartSec;
liCurrentPosition.QuadPart *= 512;
SetFilePointerEx(g_FatPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);
ReadSize = (DWORD)(SectorCount * 512);
bRet = ReadFile(g_FatPhyDrive, Buffer, ReadSize, &dwSize, NULL);
if (bRet == FALSE || dwSize != ReadSize)
{
}
return 1;
}
static int GetVentoyVersion(int PhyDrive, ventoy_disk *disk)
{
int ret = 1;
BOOL bRet;
DWORD dwBytes;
UINT64 Part2Offset;
HANDLE Handle = INVALID_HANDLE_VALUE;
VTOY_GPT_INFO *pGPT = NULL;
CHAR Drive[64];
void *flfile = NULL;
UCHAR MbrData[] =
{
0xEB, 0x63, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44, 0x00, 0x52, 0x64, 0x00, 0x20, 0x45, 0x72, 0x0D,
};
sprintf_s(Drive, sizeof(Drive), "\\\\.\\PhysicalDrive%d", PhyDrive);
Handle = CreateFileA(Drive, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (Handle == INVALID_HANDLE_VALUE)
{
vlog("CreateFileA %s failed %u\n", Drive, LASTERR);
goto out;
}
pGPT = zalloc(sizeof(VTOY_GPT_INFO));
if (!pGPT)
{
goto out;
}
bRet = ReadFile(Handle, pGPT, sizeof(VTOY_GPT_INFO), &dwBytes, NULL);
if (!bRet || dwBytes != sizeof(VTOY_GPT_INFO))
{
vlog("ReadFile failed %u\n", LASTERR);
goto out;
}
if (memcmp(pGPT->MBR.BootCode, MbrData, 0x30) || memcmp(pGPT->MBR.BootCode + 0x190, MbrData + 0x30, 0x10))
{
vlog("Invalid MBR Code %u\n", LASTERR);
goto out;
}
if (pGPT->MBR.PartTbl[0].FsFlag == 0xEE)
{
if (memcmp(pGPT->Head.Signature, "EFI PART", 8))
{
vlog("Invalid GPT Signature\n");
goto out;
}
Part2Offset = pGPT->PartTbl[1].StartLBA;
disk->cur_part_style = 1;
}
else
{
Part2Offset = pGPT->MBR.PartTbl[1].StartSectorId;
disk->cur_part_style = 0;
}
g_FatPhyDrive = Handle;
g_Part2StartSec = Part2Offset;
fl_init();
if (0 == fl_attach_media(VentoyFatDiskRead, NULL))
{
ret = GetVentoyVersionFromFatFile(disk->cur_ventoy_ver, sizeof(disk->cur_ventoy_ver));
if (ret == 0)
{
flfile = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
if (flfile)
{
disk->cur_secureboot = 1;
fl_fclose(flfile);
}
}
}
fl_shutdown();
out:
CHECK_FREE(pGPT);
CHECK_CLOSE_HANDLE(Handle);
return ret;
}
int CheckRuntimeEnvironment(char Letter, ventoy_disk *disk)
{
int PhyDrive;
UINT64 Offset = 0;
char Drive[32];
DWORD FsFlag;
CHAR Vendor[128] = { 0 };
CHAR Product[128] = { 0 };
CHAR FsName[MAX_PATH];
PhyDrive = GetPhyDriveByLogicalDrive(Letter, &Offset);
if (PhyDrive < 0)
{
vlog("GetPhyDriveByLogicalDrive failed %d %llu\n", PhyDrive, (ULONGLONG)Offset);
return 1;
}
if (Offset != 1048576)
{
vlog("Partition offset is NOT 1MB. This is NOT ventoy image partition (%llu)\n", (ULONGLONG)Offset);
return 1;
}
if (GetPhyDriveInfo(PhyDrive, &Offset, Vendor, Product) != 0)
{
vlog("GetPhyDriveInfo failed\n");
return 1;
}
sprintf_s(disk->cur_capacity, sizeof(disk->cur_capacity), "%dGB", (int)ventoy_get_human_readable_gb(Offset));
sprintf_s(disk->cur_model, sizeof(disk->cur_model), "%s %s", Vendor, Product);
scnprintf(Drive, sizeof(Drive), "%C:\\", Letter);
if (0 == GetVolumeInformationA(Drive, NULL, 0, NULL, NULL, &FsFlag, FsName, MAX_PATH))
{
vlog("GetVolumeInformationA failed %u\n", LASTERR);
return 1;
}
if (_stricmp(FsName, "NTFS") == 0)
{
disk->pathcase = 1;
}
strlcpy(disk->cur_fsname, FsName);
if (GetVentoyVersion(PhyDrive, disk) != 0)
{
vlog("GetVentoyVersion failed %u\n", LASTERR);
return 1;
}
return 0;
}
static volatile int g_thread_stop = 0;
static HANDLE g_writeback_thread;
static HANDLE g_writeback_event;
DWORD WINAPI ventoy_local_thread_run(LPVOID lpParameter)
{
ventoy_http_writeback_pf callback = (ventoy_http_writeback_pf)lpParameter;
while (1)
{
WaitForSingleObject(g_writeback_event, INFINITE);
if (g_thread_stop)
{
break;
}
else
{
callback();
}
}
return 0;
}
void ventoy_set_writeback_event(void)
{
SetEvent(g_writeback_event);
}
int ventoy_start_writeback_thread(ventoy_http_writeback_pf callback)
{
g_thread_stop = 0;
g_writeback_event = CreateEventA(NULL, FALSE, FALSE, "VTOYWRBK");
g_writeback_thread = CreateThread(NULL, 0, ventoy_local_thread_run, callback, 0, NULL);
return 0;
}
void ventoy_stop_writeback_thread(void)
{
g_thread_stop = 1;
ventoy_set_writeback_event();
WaitForSingleObject(g_writeback_thread, INFINITE);
CHECK_CLOSE_HANDLE(g_writeback_thread);
CHECK_CLOSE_HANDLE(g_writeback_event);
}
int ventoy_read_file_to_buf(const char *FileName, int ExtLen, void **Bufer, int *BufLen)
{
int UTF8 = 0;
int Size = 0;
BOOL bRet;
DWORD dwBytes;
HANDLE hFile;
char *buffer = NULL;
WCHAR FilePathW[MAX_PATH];
UTF8 = IsUTF8Encode(FileName);
if (UTF8)
{
Utf8ToUtf16(FileName, FilePathW);
hFile = CreateFileW(FilePathW, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
}
else
{
hFile = CreateFileA(FileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
}
if (hFile == INVALID_HANDLE_VALUE)
{
vlog("Failed to open %s %u\n", FileName, LASTERR);
return 1;
}
Size = (int)GetFileSize(hFile, NULL);
buffer = malloc(Size + ExtLen);
if (!buffer)
{
vlog("Failed to alloc file buffer\n");
CloseHandle(hFile);
return 1;
}
bRet = ReadFile(hFile, buffer, (DWORD)Size, &dwBytes, NULL);
if ((!bRet) || ((DWORD)Size != dwBytes))
{
vlog("Failed to read file <%s> %u err:%u", FileName, dwBytes, LASTERR);
CloseHandle(hFile);
free(buffer);
return 1;
}
*Bufer = buffer;
*BufLen = Size;
CloseHandle(hFile);
return 0;
}
int ventoy_write_buf_to_file(const char *FileName, void *Bufer, int BufLen)
{
BOOL bRet;
DWORD dwBytes;
HANDLE hFile;
hFile = CreateFileA(FileName, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
if (hFile == INVALID_HANDLE_VALUE)
{
vlog("CreateFile %s failed %u\n", FileName, LASTERR);
return 1;
}
bRet = WriteFile(hFile, Bufer, (DWORD)BufLen, &dwBytes, NULL);
if ((!bRet) || ((DWORD)BufLen != dwBytes))
{
vlog("Failed to write file <%s> %u err:%u", FileName, dwBytes, LASTERR);
CloseHandle(hFile);
return 1;
}
FlushFileBuffers(hFile);
CloseHandle(hFile);
return 0;
}
int ventoy_copy_file(const char *a, const char *b)
{
CopyFileA(a, b, FALSE);
return 0;
}

View File

@@ -0,0 +1,22 @@
File IO Lib API
-=-=-=-=-=-=-=-=-
void fl_init(void)
Called to initialize FAT IO library.
This should be called prior to any other functions.
void fl_attach_locks(void (*lock)(void), void (*unlock)(void))
[Optional] File system thread safety locking functions.
For thread safe operation, you should provide lock() and unlock() functions.
Note that locking primitive used must support recursive locking, i.e lock() called within an already <20>locked<65> region.
int fl_attach_media(fn_diskio_read rd, fn_diskio_write wr)
This function is used to attach system specific disk/media access functions.
This should be done subsequent to calling fl_init() and fl_attach_locks() (if locking required).
void fl_shutdown(void)
Shutdown the FAT IO library. This purges any un-saved data back to disk.

View File

@@ -0,0 +1,345 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@@ -0,0 +1,53 @@
File IO Lib Options
-=-=-=-=-=-=-=-=-=-
See defines in fat_opts.h:
FATFS_IS_LITTLE_ENDIAN [1/0]
Which endian is your system? Set to 1 for little endian, 0 for big endian.
FATFS_MAX_LONG_FILENAME [260]
By default, 260 characters (max LFN length). Increase this to support greater path depths.
FATFS_MAX_OPEN_FILES
The more files you wish to have concurrently open, the greater this number should be.
This increases the number of FL_FILE file structures in the library, each of these is around 1K in size (assuming 512 byte sectors).
FAT_BUFFER_SECTORS
Minimum is 1, more increases performance.
This defines how many FAT sectors can be buffered per FAT_BUFFER entry.
FAT_BUFFERS
Minimum is 1, more increases performance.
This defines how many FAT buffer entries are available.
Memory usage is FAT_BUFFERS * FAT_BUFFER_SECTORS * FAT_SECTOR_SIZE
FATFS_INC_WRITE_SUPPORT
Support file write functionality.
FAT_SECTOR_SIZE
Sector size used by buffers. Most likely to be 512 bytes (standard for ATA/IDE).
FAT_PRINTF
A define that allows the File IO library to print to console/stdout.
Provide your own printf function if printf not available.
FAT_CLUSTER_CACHE_ENTRIES
Size of cluster chain cache (can be undefined if not required).
Mem used = FAT_CLUSTER_CACHE_ENTRIES * 4 * 2
Improves access speed considerably.
FATFS_INC_LFN_SUPPORT [1/0]
Enable/Disable support for long filenames.
FATFS_DIR_LIST_SUPPORT [1/0]
Include support for directory listing.
FATFS_INC_TIME_DATE_SUPPORT [1/0]
Use time/date functions provided by time.h to update creation & modification timestamps.
FATFS_INC_FORMAT_SUPPORT
Include support for formatting disks (FAT16 only).
FAT_PRINTF_NOINC_STDIO
Disable use of printf & inclusion of stdio.h

View File

@@ -0,0 +1,24 @@
Revision History
-=-=-=-=-=-=-=-=-
v2.6.11 - Fix compilation with GCC on 64-bit machines
v2.6.10 - Added support for FAT32 format.
V2.6.9 - Added support for time & date handling.
V2.6.8 - Fixed error with FSINFO sector write.
V2.6.7 - Added fgets().
Fixed C warnings, removed dependancy on some string.h functions.
V2.6.6 <20> Massive read + write performance improvements.
V2.6.5 <20> Bug fixes for big endian systems.
V2.6.4 <20> Further bug fixes and performance improvements for write operations.
V2.6.3 <20> Peformance improvements, FAT16 formatting support. Various bug fixes.
V2.6 - Basic support for FAT16 added (18-04-10).
V2.5 - Code cleaned up. Many bugs fixed. Thread safety functions added.
V2.x - Write support added as well as better stdio like API.
V1.0 - Rewrite of all code to enable multiple files to be opened and provides a
better file API.
Also better string matching, and generally better C code than origonal
version.
V0.1c - Fetch_ID_Max_LBA() function added to retrieve Drive infomation and stoping
the drive reads from addressing a sector that is out of range.
V0.1b - fopen(), fgetc(), fopenDIR() using new software stack for IDE and FAT32
access.
V0.1a - First release (27/12/03); fopen(), fgetc() unbuffered reads.

View File

@@ -0,0 +1,10 @@
FAT File IO Library License
-=-=-=-=-=-=-=-=-=-=-=-=-=-
This versions license: GPL
If you include GPL software in your project, you must release the source code of that project too.
If you would like a version with a more permissive license for use in closed source commercial applications please contact me for details.
Email: admin@ultra-embedded.com

View File

@@ -0,0 +1,40 @@
Media Access API
-=-=-=-=-=-=-=-=-
int media_read(uint32 sector, uint8 *buffer, uint32 sector_count)
Params:
Sector: 32-bit sector number
Buffer: Target buffer to read n sectors of data into.
Sector_count: Number of sectors to read.
Return:
int, 1 = success, 0 = failure.
Description:
Application/target specific disk/media read function.
Sector number (sectors are usually 512 byte pages) to read.
Media Write API
int media_write(uint32 sector, uint8 *buffer, uint32 sector_count)
Params:
Sector: 32-bit sector number
Buffer: Target buffer to write n sectors of data from.
Sector_count: Number of sectors to write.
Return:
int, 1 = success, 0 = failure.
Description:
Application/target specific disk/media write function.
Sector number (sectors are usually 512 byte pages) to write to.
File IO Library Linkage
Use the following API to attach the media IO functions to the File IO library.
int fl_attach_media(fn_diskio_read rd, fn_diskio_write wr)

View File

@@ -0,0 +1,907 @@
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// FAT16/32 File IO Library
// V2.6
// Ultra-Embedded.com
// Copyright 2003 - 2012
//
// Email: admin@ultra-embedded.com
//
// License: GPL
// If you would like a version with a more permissive license for use in
// closed source commercial applications please contact me for details.
//-----------------------------------------------------------------------------
//
// This file is part of FAT File IO Library.
//
// FAT File IO Library 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.
//
// FAT File IO 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with FAT File IO Library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#include <string.h>
#include "fat_defs.h"
#include "fat_access.h"
#include "fat_table.h"
#include "fat_write.h"
#include "fat_string.h"
#include "fat_misc.h"
//-----------------------------------------------------------------------------
// fatfs_init: Load FAT Parameters
//-----------------------------------------------------------------------------
int fatfs_init(struct fatfs *fs)
{
uint8 num_of_fats;
uint16 reserved_sectors;
uint32 FATSz;
uint32 root_dir_sectors;
uint32 total_sectors;
uint32 data_sectors;
uint32 count_of_clusters;
uint8 valid_partition = 0;
fs->currentsector.address = FAT32_INVALID_CLUSTER;
fs->currentsector.dirty = 0;
fs->next_free_cluster = 0; // Invalid
fatfs_fat_init(fs);
// Make sure we have a read function (write function is optional)
if (!fs->disk_io.read_media)
return FAT_INIT_MEDIA_ACCESS_ERROR;
// MBR: Sector 0 on the disk
// NOTE: Some removeable media does not have this.
// Load MBR (LBA 0) into the 512 byte buffer
if (!fs->disk_io.read_media(0, fs->currentsector.sector, 1))
return FAT_INIT_MEDIA_ACCESS_ERROR;
// Make Sure 0x55 and 0xAA are at end of sector
// (this should be the case regardless of the MBR or boot sector)
if (fs->currentsector.sector[SIGNATURE_POSITION] != 0x55 || fs->currentsector.sector[SIGNATURE_POSITION+1] != 0xAA)
return FAT_INIT_INVALID_SIGNATURE;
// Now check again using the access function to prove endian conversion function
if (GET_16BIT_WORD(fs->currentsector.sector, SIGNATURE_POSITION) != SIGNATURE_VALUE)
return FAT_INIT_ENDIAN_ERROR;
// Verify packed structures
if (sizeof(struct fat_dir_entry) != FAT_DIR_ENTRY_SIZE)
return FAT_INIT_STRUCT_PACKING;
// Check the partition type code
switch(fs->currentsector.sector[PARTITION1_TYPECODE_LOCATION])
{
case 0x0B:
case 0x06:
case 0x0C:
case 0x0E:
case 0x0F:
case 0x05:
valid_partition = 1;
break;
case 0x00:
valid_partition = 0;
break;
default:
if (fs->currentsector.sector[PARTITION1_TYPECODE_LOCATION] <= 0x06)
valid_partition = 1;
break;
}
// Read LBA Begin for the file system
if (valid_partition)
fs->lba_begin = GET_32BIT_WORD(fs->currentsector.sector, PARTITION1_LBA_BEGIN_LOCATION);
// Else possibly MBR less disk
else
fs->lba_begin = 0;
// Load Volume 1 table into sector buffer
// (We may already have this in the buffer if MBR less drive!)
if (!fs->disk_io.read_media(fs->lba_begin, fs->currentsector.sector, 1))
return FAT_INIT_MEDIA_ACCESS_ERROR;
// Make sure there are 512 bytes per cluster
if (GET_16BIT_WORD(fs->currentsector.sector, 0x0B) != FAT_SECTOR_SIZE)
return FAT_INIT_INVALID_SECTOR_SIZE;
// Load Parameters of FAT partition
fs->sectors_per_cluster = fs->currentsector.sector[BPB_SECPERCLUS];
reserved_sectors = GET_16BIT_WORD(fs->currentsector.sector, BPB_RSVDSECCNT);
num_of_fats = fs->currentsector.sector[BPB_NUMFATS];
fs->root_entry_count = GET_16BIT_WORD(fs->currentsector.sector, BPB_ROOTENTCNT);
if(GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16) != 0)
fs->fat_sectors = GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16);
else
fs->fat_sectors = GET_32BIT_WORD(fs->currentsector.sector, BPB_FAT32_FATSZ32);
// For FAT32 (which this may be)
fs->rootdir_first_cluster = GET_32BIT_WORD(fs->currentsector.sector, BPB_FAT32_ROOTCLUS);
fs->fs_info_sector = GET_16BIT_WORD(fs->currentsector.sector, BPB_FAT32_FSINFO);
// For FAT16 (which this may be), rootdir_first_cluster is actuall rootdir_first_sector
fs->rootdir_first_sector = reserved_sectors + (num_of_fats * fs->fat_sectors);
fs->rootdir_sectors = ((fs->root_entry_count * 32) + (FAT_SECTOR_SIZE - 1)) / FAT_SECTOR_SIZE;
// First FAT LBA address
fs->fat_begin_lba = fs->lba_begin + reserved_sectors;
// The address of the first data cluster on this volume
fs->cluster_begin_lba = fs->fat_begin_lba + (num_of_fats * fs->fat_sectors);
if (GET_16BIT_WORD(fs->currentsector.sector, 0x1FE) != 0xAA55) // This signature should be AA55
return FAT_INIT_INVALID_SIGNATURE;
// Calculate the root dir sectors
root_dir_sectors = ((GET_16BIT_WORD(fs->currentsector.sector, BPB_ROOTENTCNT) * 32) + (GET_16BIT_WORD(fs->currentsector.sector, BPB_BYTSPERSEC) - 1)) / GET_16BIT_WORD(fs->currentsector.sector, BPB_BYTSPERSEC);
if(GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16) != 0)
FATSz = GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16);
else
FATSz = GET_32BIT_WORD(fs->currentsector.sector, BPB_FAT32_FATSZ32);
if(GET_16BIT_WORD(fs->currentsector.sector, BPB_TOTSEC16) != 0)
total_sectors = GET_16BIT_WORD(fs->currentsector.sector, BPB_TOTSEC16);
else
total_sectors = GET_32BIT_WORD(fs->currentsector.sector, BPB_TOTSEC32);
data_sectors = total_sectors - (GET_16BIT_WORD(fs->currentsector.sector, BPB_RSVDSECCNT) + (fs->currentsector.sector[BPB_NUMFATS] * FATSz) + root_dir_sectors);
// Find out which version of FAT this is...
if (fs->sectors_per_cluster != 0)
{
count_of_clusters = data_sectors / fs->sectors_per_cluster;
if(count_of_clusters < 4085)
// Volume is FAT12
return FAT_INIT_WRONG_FILESYS_TYPE;
else if(count_of_clusters < 65525)
{
// Clear this FAT32 specific param
fs->rootdir_first_cluster = 0;
// Volume is FAT16
fs->fat_type = FAT_TYPE_16;
return FAT_INIT_OK;
}
else
{
// Volume is FAT32
fs->fat_type = FAT_TYPE_32;
return FAT_INIT_OK;
}
}
else
return FAT_INIT_WRONG_FILESYS_TYPE;
}
//-----------------------------------------------------------------------------
// fatfs_lba_of_cluster: This function converts a cluster number into a sector /
// LBA number.
//-----------------------------------------------------------------------------
uint32 fatfs_lba_of_cluster(struct fatfs *fs, uint32 Cluster_Number)
{
if (fs->fat_type == FAT_TYPE_16)
return (fs->cluster_begin_lba + (fs->root_entry_count * 32 / FAT_SECTOR_SIZE) + ((Cluster_Number-2) * fs->sectors_per_cluster));
else
return ((fs->cluster_begin_lba + ((Cluster_Number-2)*fs->sectors_per_cluster)));
}
//-----------------------------------------------------------------------------
// fatfs_sector_read:
//-----------------------------------------------------------------------------
int fatfs_sector_read(struct fatfs *fs, uint32 lba, uint8 *target, uint32 count)
{
return fs->disk_io.read_media(lba, target, count);
}
//-----------------------------------------------------------------------------
// fatfs_sector_write:
//-----------------------------------------------------------------------------
int fatfs_sector_write(struct fatfs *fs, uint32 lba, uint8 *target, uint32 count)
{
return fs->disk_io.write_media(lba, target, count);
}
//-----------------------------------------------------------------------------
// fatfs_sector_reader: From the provided startcluster and sector offset
// Returns True if success, returns False if not (including if read out of range)
//-----------------------------------------------------------------------------
int fatfs_sector_reader(struct fatfs *fs, uint32 start_cluster, uint32 offset, uint8 *target)
{
uint32 sector_to_read = 0;
uint32 cluster_to_read = 0;
uint32 cluster_chain = 0;
uint32 i;
uint32 lba;
// FAT16 Root directory
if (fs->fat_type == FAT_TYPE_16 && start_cluster == 0)
{
if (offset < fs->rootdir_sectors)
lba = fs->lba_begin + fs->rootdir_first_sector + offset;
else
return 0;
}
// FAT16/32 Other
else
{
// Set start of cluster chain to initial value
cluster_chain = start_cluster;
// Find parameters
cluster_to_read = offset / fs->sectors_per_cluster;
sector_to_read = offset - (cluster_to_read*fs->sectors_per_cluster);
// Follow chain to find cluster to read
for (i=0; i<cluster_to_read; i++)
cluster_chain = fatfs_find_next_cluster(fs, cluster_chain);
// If end of cluster chain then return false
if (cluster_chain == FAT32_LAST_CLUSTER)
return 0;
// Calculate sector address
lba = fatfs_lba_of_cluster(fs, cluster_chain)+sector_to_read;
}
// User provided target array
if (target)
return fs->disk_io.read_media(lba, target, 1);
// Else read sector if not already loaded
else if (lba != fs->currentsector.address)
{
fs->currentsector.address = lba;
return fs->disk_io.read_media(fs->currentsector.address, fs->currentsector.sector, 1);
}
else
return 1;
}
//-----------------------------------------------------------------------------
// fatfs_read_sector: Read from the provided cluster and sector offset
// Returns True if success, returns False if not
//-----------------------------------------------------------------------------
int fatfs_read_sector(struct fatfs *fs, uint32 cluster, uint32 sector, uint8 *target)
{
// FAT16 Root directory
if (fs->fat_type == FAT_TYPE_16 && cluster == 0)
{
uint32 lba;
// In FAT16, there are a limited amount of sectors in root dir!
if (sector < fs->rootdir_sectors)
lba = fs->lba_begin + fs->rootdir_first_sector + sector;
else
return 0;
// User target buffer passed in
if (target)
{
// Read from disk
return fs->disk_io.read_media(lba, target, 1);
}
else
{
// Calculate read address
fs->currentsector.address = lba;
// Read from disk
return fs->disk_io.read_media(fs->currentsector.address, fs->currentsector.sector, 1);
}
}
// FAT16/32 Other
else
{
// User target buffer passed in
if (target)
{
// Calculate read address
uint32 lba = fatfs_lba_of_cluster(fs, cluster) + sector;
// Read from disk
return fs->disk_io.read_media(lba, target, 1);
}
else
{
// Calculate write address
fs->currentsector.address = fatfs_lba_of_cluster(fs, cluster)+sector;
// Read from disk
return fs->disk_io.read_media(fs->currentsector.address, fs->currentsector.sector, 1);
}
}
}
//-----------------------------------------------------------------------------
// fatfs_write_sector: Write to the provided cluster and sector offset
// Returns True if success, returns False if not
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int fatfs_write_sector(struct fatfs *fs, uint32 cluster, uint32 sector, uint8 *target)
{
// No write access?
if (!fs->disk_io.write_media)
return 0;
// FAT16 Root directory
if (fs->fat_type == FAT_TYPE_16 && cluster == 0)
{
uint32 lba;
// In FAT16 we cannot extend the root dir!
if (sector < fs->rootdir_sectors)
lba = fs->lba_begin + fs->rootdir_first_sector + sector;
else
return 0;
// User target buffer passed in
if (target)
{
// Write to disk
return fs->disk_io.write_media(lba, target, 1);
}
else
{
// Calculate write address
fs->currentsector.address = lba;
// Write to disk
return fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1);
}
}
// FAT16/32 Other
else
{
// User target buffer passed in
if (target)
{
// Calculate write address
uint32 lba = fatfs_lba_of_cluster(fs, cluster) + sector;
// Write to disk
return fs->disk_io.write_media(lba, target, 1);
}
else
{
// Calculate write address
fs->currentsector.address = fatfs_lba_of_cluster(fs, cluster)+sector;
// Write to disk
return fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1);
}
}
}
#endif
//-----------------------------------------------------------------------------
// fatfs_show_details: Show the details about the filesystem
//-----------------------------------------------------------------------------
void fatfs_show_details(struct fatfs *fs)
{
FAT_PRINTF(("FAT details:\r\n"));
FAT_PRINTF((" Type =%s", (fs->fat_type == FAT_TYPE_32) ? "FAT32": "FAT16"));
FAT_PRINTF((" Root Dir First Cluster = %x\r\n", fs->rootdir_first_cluster));
FAT_PRINTF((" FAT Begin LBA = 0x%x\r\n",fs->fat_begin_lba));
FAT_PRINTF((" Cluster Begin LBA = 0x%x\r\n",fs->cluster_begin_lba));
FAT_PRINTF((" Sectors Per Cluster = %d\r\n", fs->sectors_per_cluster));
}
//-----------------------------------------------------------------------------
// fatfs_get_root_cluster: Get the root dir cluster
//-----------------------------------------------------------------------------
uint32 fatfs_get_root_cluster(struct fatfs *fs)
{
// NOTE: On FAT16 this will be 0 which has a special meaning...
return fs->rootdir_first_cluster;
}
//-------------------------------------------------------------
// fatfs_get_file_entry: Find the file entry for a filename
//-------------------------------------------------------------
uint32 fatfs_get_file_entry(struct fatfs *fs, uint32 Cluster, char *name_to_find, struct fat_dir_entry *sfEntry)
{
uint8 item=0;
uint16 recordoffset = 0;
uint8 i=0;
int x=0;
char *long_filename = NULL;
char short_filename[13];
struct lfn_cache lfn;
int dotRequired = 0;
struct fat_dir_entry *directoryEntry;
fatfs_lfn_cache_init(&lfn, 1);
// Main cluster following loop
while (1)
{
// Read sector
if (fatfs_sector_reader(fs, Cluster, x++, 0)) // If sector read was successfull
{
// Analyse Sector
for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
{
// Create the multiplier for sector access
recordoffset = FAT_DIR_ENTRY_SIZE * item;
// Overlay directory entry over buffer
directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset);
#if FATFS_INC_LFN_SUPPORT
// Long File Name Text Found
if (fatfs_entry_lfn_text(directoryEntry) )
fatfs_lfn_cache_entry(&lfn, fs->currentsector.sector+recordoffset);
// If Invalid record found delete any long file name information collated
else if (fatfs_entry_lfn_invalid(directoryEntry) )
fatfs_lfn_cache_init(&lfn, 0);
// Normal SFN Entry and Long text exists
else if (fatfs_entry_lfn_exists(&lfn, directoryEntry) )
{
long_filename = fatfs_lfn_cache_get(&lfn);
// Compare names to see if they match
if (fatfs_compare_names(long_filename, name_to_find))
{
memcpy(sfEntry,directoryEntry,sizeof(struct fat_dir_entry));
return 1;
}
fatfs_lfn_cache_init(&lfn, 0);
}
else
#endif
// Normal Entry, only 8.3 Text
if (fatfs_entry_sfn_only(directoryEntry) )
{
memset(short_filename, 0, sizeof(short_filename));
// Copy name to string
for (i=0; i<8; i++)
short_filename[i] = directoryEntry->Name[i];
// Extension
dotRequired = 0;
for (i=8; i<11; i++)
{
short_filename[i+1] = directoryEntry->Name[i];
if (directoryEntry->Name[i] != ' ')
dotRequired = 1;
}
// Dot only required if extension present
if (dotRequired)
{
// If not . or .. entry
if (short_filename[0]!='.')
short_filename[8] = '.';
else
short_filename[8] = ' ';
}
else
short_filename[8] = ' ';
// Compare names to see if they match
if (fatfs_compare_names(short_filename, name_to_find))
{
memcpy(sfEntry,directoryEntry,sizeof(struct fat_dir_entry));
return 1;
}
fatfs_lfn_cache_init(&lfn, 0);
}
} // End of if
}
else
break;
} // End of while loop
return 0;
}
//-------------------------------------------------------------
// fatfs_sfn_exists: Check if a short filename exists.
// NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY
//-------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int fatfs_sfn_exists(struct fatfs *fs, uint32 Cluster, char *shortname)
{
uint8 item=0;
uint16 recordoffset = 0;
int x=0;
struct fat_dir_entry *directoryEntry;
// Main cluster following loop
while (1)
{
// Read sector
if (fatfs_sector_reader(fs, Cluster, x++, 0)) // If sector read was successfull
{
// Analyse Sector
for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
{
// Create the multiplier for sector access
recordoffset = FAT_DIR_ENTRY_SIZE * item;
// Overlay directory entry over buffer
directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset);
#if FATFS_INC_LFN_SUPPORT
// Long File Name Text Found
if (fatfs_entry_lfn_text(directoryEntry) )
;
// If Invalid record found delete any long file name information collated
else if (fatfs_entry_lfn_invalid(directoryEntry) )
;
else
#endif
// Normal Entry, only 8.3 Text
if (fatfs_entry_sfn_only(directoryEntry) )
{
if (strncmp((const char*)directoryEntry->Name, shortname, 11)==0)
return 1;
}
} // End of if
}
else
break;
} // End of while loop
return 0;
}
#endif
//-------------------------------------------------------------
// fatfs_update_timestamps: Update date/time details
//-------------------------------------------------------------
#if FATFS_INC_TIME_DATE_SUPPORT
int fatfs_update_timestamps(struct fat_dir_entry *directoryEntry, int create, int modify, int access)
{
time_t time_now;
struct tm * time_info;
uint16 fat_time;
uint16 fat_date;
// Get system time
time(&time_now);
// Convert to local time
time_info = localtime(&time_now);
// Convert time to FAT format
fat_time = fatfs_convert_to_fat_time(time_info->tm_hour, time_info->tm_min, time_info->tm_sec);
// Convert date to FAT format
fat_date = fatfs_convert_to_fat_date(time_info->tm_mday, time_info->tm_mon + 1, time_info->tm_year + 1900);
// Update requested fields
if (create)
{
directoryEntry->CrtTime[1] = fat_time >> 8;
directoryEntry->CrtTime[0] = fat_time >> 0;
directoryEntry->CrtDate[1] = fat_date >> 8;
directoryEntry->CrtDate[0] = fat_date >> 0;
}
if (modify)
{
directoryEntry->WrtTime[1] = fat_time >> 8;
directoryEntry->WrtTime[0] = fat_time >> 0;
directoryEntry->WrtDate[1] = fat_date >> 8;
directoryEntry->WrtDate[0] = fat_date >> 0;
}
if (access)
{
directoryEntry->LstAccDate[1] = fat_time >> 8;
directoryEntry->LstAccDate[0] = fat_time >> 0;
directoryEntry->LstAccDate[1] = fat_date >> 8;
directoryEntry->LstAccDate[0] = fat_date >> 0;
}
return 1;
}
#endif
//-------------------------------------------------------------
// fatfs_update_file_length: Find a SFN entry and update it
// NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY
//-------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int fatfs_update_file_length(struct fatfs *fs, uint32 Cluster, char *shortname, uint32 fileLength)
{
uint8 item=0;
uint16 recordoffset = 0;
int x=0;
struct fat_dir_entry *directoryEntry;
// No write access?
if (!fs->disk_io.write_media)
return 0;
// Main cluster following loop
while (1)
{
// Read sector
if (fatfs_sector_reader(fs, Cluster, x++, 0)) // If sector read was successfull
{
// Analyse Sector
for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
{
// Create the multiplier for sector access
recordoffset = FAT_DIR_ENTRY_SIZE * item;
// Overlay directory entry over buffer
directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset);
#if FATFS_INC_LFN_SUPPORT
// Long File Name Text Found
if (fatfs_entry_lfn_text(directoryEntry) )
;
// If Invalid record found delete any long file name information collated
else if (fatfs_entry_lfn_invalid(directoryEntry) )
;
// Normal Entry, only 8.3 Text
else
#endif
if (fatfs_entry_sfn_only(directoryEntry) )
{
if (strncmp((const char*)directoryEntry->Name, shortname, 11)==0)
{
directoryEntry->FileSize = FAT_HTONL(fileLength);
#if FATFS_INC_TIME_DATE_SUPPORT
// Update access / modify time & date
fatfs_update_timestamps(directoryEntry, 0, 1, 1);
#endif
// Update sfn entry
memcpy((uint8*)(fs->currentsector.sector+recordoffset), (uint8*)directoryEntry, sizeof(struct fat_dir_entry));
// Write sector back
return fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1);
}
}
} // End of if
}
else
break;
} // End of while loop
return 0;
}
#endif
//-------------------------------------------------------------
// fatfs_mark_file_deleted: Find a SFN entry and mark if as deleted
// NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY
//-------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int fatfs_mark_file_deleted(struct fatfs *fs, uint32 Cluster, char *shortname)
{
uint8 item=0;
uint16 recordoffset = 0;
int x=0;
struct fat_dir_entry *directoryEntry;
// No write access?
if (!fs->disk_io.write_media)
return 0;
// Main cluster following loop
while (1)
{
// Read sector
if (fatfs_sector_reader(fs, Cluster, x++, 0)) // If sector read was successfull
{
// Analyse Sector
for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
{
// Create the multiplier for sector access
recordoffset = FAT_DIR_ENTRY_SIZE * item;
// Overlay directory entry over buffer
directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset);
#if FATFS_INC_LFN_SUPPORT
// Long File Name Text Found
if (fatfs_entry_lfn_text(directoryEntry) )
;
// If Invalid record found delete any long file name information collated
else if (fatfs_entry_lfn_invalid(directoryEntry) )
;
// Normal Entry, only 8.3 Text
else
#endif
if (fatfs_entry_sfn_only(directoryEntry) )
{
if (strncmp((const char *)directoryEntry->Name, shortname, 11)==0)
{
// Mark as deleted
directoryEntry->Name[0] = FILE_HEADER_DELETED;
#if FATFS_INC_TIME_DATE_SUPPORT
// Update access / modify time & date
fatfs_update_timestamps(directoryEntry, 0, 1, 1);
#endif
// Update sfn entry
memcpy((uint8*)(fs->currentsector.sector+recordoffset), (uint8*)directoryEntry, sizeof(struct fat_dir_entry));
// Write sector back
return fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1);
}
}
} // End of if
}
else
break;
} // End of while loop
return 0;
}
#endif
//-----------------------------------------------------------------------------
// fatfs_list_directory_start: Initialise a directory listing procedure
//-----------------------------------------------------------------------------
#if FATFS_DIR_LIST_SUPPORT
void fatfs_list_directory_start(struct fatfs *fs, struct fs_dir_list_status *dirls, uint32 StartCluster)
{
dirls->cluster = StartCluster;
dirls->sector = 0;
dirls->offset = 0;
}
#endif
//-----------------------------------------------------------------------------
// fatfs_list_directory_next: Get the next entry in the directory.
// Returns: 1 = found, 0 = end of listing
//-----------------------------------------------------------------------------
#if FATFS_DIR_LIST_SUPPORT
int fatfs_list_directory_next(struct fatfs *fs, struct fs_dir_list_status *dirls, struct fs_dir_ent *entry)
{
uint8 i,item;
uint16 recordoffset;
struct fat_dir_entry *directoryEntry;
char *long_filename = NULL;
char short_filename[13];
struct lfn_cache lfn;
int dotRequired = 0;
int result = 0;
// Initialise LFN cache first
fatfs_lfn_cache_init(&lfn, 0);
while (1)
{
// If data read OK
if (fatfs_sector_reader(fs, dirls->cluster, dirls->sector, 0))
{
// Maximum of 16 directory entries
for (item = dirls->offset; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
{
// Increase directory offset
recordoffset = FAT_DIR_ENTRY_SIZE * item;
// Overlay directory entry over buffer
directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset);
#if FATFS_INC_LFN_SUPPORT
// Long File Name Text Found
if ( fatfs_entry_lfn_text(directoryEntry) )
fatfs_lfn_cache_entry(&lfn, fs->currentsector.sector+recordoffset);
// If Invalid record found delete any long file name information collated
else if ( fatfs_entry_lfn_invalid(directoryEntry) )
fatfs_lfn_cache_init(&lfn, 0);
// Normal SFN Entry and Long text exists
else if (fatfs_entry_lfn_exists(&lfn, directoryEntry) )
{
// Get text
long_filename = fatfs_lfn_cache_get(&lfn);
#if defined(_MSC_VER) || defined(WIN32)
strcpy_s(entry->filename, FATFS_MAX_LONG_FILENAME - 1, long_filename);
#else
strncpy(entry->filename, long_filename, FATFS_MAX_LONG_FILENAME - 1);
#endif
if (fatfs_entry_is_dir(directoryEntry))
entry->is_dir = 1;
else
entry->is_dir = 0;
#if FATFS_INC_TIME_DATE_SUPPORT
// Get time / dates
entry->create_time = ((uint16)directoryEntry->CrtTime[1] << 8) | directoryEntry->CrtTime[0];
entry->create_date = ((uint16)directoryEntry->CrtDate[1] << 8) | directoryEntry->CrtDate[0];
entry->access_date = ((uint16)directoryEntry->LstAccDate[1] << 8) | directoryEntry->LstAccDate[0];
entry->write_time = ((uint16)directoryEntry->WrtTime[1] << 8) | directoryEntry->WrtTime[0];
entry->write_date = ((uint16)directoryEntry->WrtDate[1] << 8) | directoryEntry->WrtDate[0];
#endif
entry->size = FAT_HTONL(directoryEntry->FileSize);
entry->cluster = (FAT_HTONS(directoryEntry->FstClusHI)<<16) | FAT_HTONS(directoryEntry->FstClusLO);
// Next starting position
dirls->offset = item + 1;
result = 1;
return 1;
}
// Normal Entry, only 8.3 Text
else
#endif
if ( fatfs_entry_sfn_only(directoryEntry) )
{
fatfs_lfn_cache_init(&lfn, 0);
memset(short_filename, 0, sizeof(short_filename));
// Copy name to string
for (i=0; i<8; i++)
short_filename[i] = directoryEntry->Name[i];
// Extension
dotRequired = 0;
for (i=8; i<11; i++)
{
short_filename[i+1] = directoryEntry->Name[i];
if (directoryEntry->Name[i] != ' ')
dotRequired = 1;
}
// Dot only required if extension present
if (dotRequired)
{
// If not . or .. entry
if (short_filename[0]!='.')
short_filename[8] = '.';
else
short_filename[8] = ' ';
}
else
short_filename[8] = ' ';
fatfs_get_sfn_display_name(entry->filename, short_filename);
if (fatfs_entry_is_dir(directoryEntry))
entry->is_dir = 1;
else
entry->is_dir = 0;
#if FATFS_INC_TIME_DATE_SUPPORT
// Get time / dates
entry->create_time = ((uint16)directoryEntry->CrtTime[1] << 8) | directoryEntry->CrtTime[0];
entry->create_date = ((uint16)directoryEntry->CrtDate[1] << 8) | directoryEntry->CrtDate[0];
entry->access_date = ((uint16)directoryEntry->LstAccDate[1] << 8) | directoryEntry->LstAccDate[0];
entry->write_time = ((uint16)directoryEntry->WrtTime[1] << 8) | directoryEntry->WrtTime[0];
entry->write_date = ((uint16)directoryEntry->WrtDate[1] << 8) | directoryEntry->WrtDate[0];
#endif
entry->size = FAT_HTONL(directoryEntry->FileSize);
entry->cluster = (FAT_HTONS(directoryEntry->FstClusHI)<<16) | FAT_HTONS(directoryEntry->FstClusLO);
// Next starting position
dirls->offset = item + 1;
result = 1;
return 1;
}
}// end of for
// If reached end of the dir move onto next sector
dirls->sector++;
dirls->offset = 0;
}
else
break;
}
return result;
}
#endif

View File

@@ -0,0 +1,133 @@
#ifndef __FAT_ACCESS_H__
#define __FAT_ACCESS_H__
#include "fat_defs.h"
#include "fat_opts.h"
//-----------------------------------------------------------------------------
// Defines
//-----------------------------------------------------------------------------
#define FAT_INIT_OK 0
#define FAT_INIT_MEDIA_ACCESS_ERROR (-1)
#define FAT_INIT_INVALID_SECTOR_SIZE (-2)
#define FAT_INIT_INVALID_SIGNATURE (-3)
#define FAT_INIT_ENDIAN_ERROR (-4)
#define FAT_INIT_WRONG_FILESYS_TYPE (-5)
#define FAT_INIT_WRONG_PARTITION_TYPE (-6)
#define FAT_INIT_STRUCT_PACKING (-7)
#define FAT_DIR_ENTRIES_PER_SECTOR (FAT_SECTOR_SIZE / FAT_DIR_ENTRY_SIZE)
//-----------------------------------------------------------------------------
// Function Pointers
//-----------------------------------------------------------------------------
typedef int (*fn_diskio_read) (uint32 sector, uint8 *buffer, uint32 sector_count);
typedef int (*fn_diskio_write)(uint32 sector, uint8 *buffer, uint32 sector_count);
//-----------------------------------------------------------------------------
// Structures
//-----------------------------------------------------------------------------
struct disk_if
{
// User supplied function pointers for disk IO
fn_diskio_read read_media;
fn_diskio_write write_media;
};
// Forward declaration
struct fat_buffer;
struct fat_buffer
{
uint8 sector[FAT_SECTOR_SIZE * FAT_BUFFER_SECTORS];
uint32 address;
int dirty;
uint8 * ptr;
// Next in chain of sector buffers
struct fat_buffer *next;
};
typedef enum eFatType
{
FAT_TYPE_16,
FAT_TYPE_32
} tFatType;
struct fatfs
{
// Filesystem globals
uint8 sectors_per_cluster;
uint32 cluster_begin_lba;
uint32 rootdir_first_cluster;
uint32 rootdir_first_sector;
uint32 rootdir_sectors;
uint32 fat_begin_lba;
uint16 fs_info_sector;
uint32 lba_begin;
uint32 fat_sectors;
uint32 next_free_cluster;
uint16 root_entry_count;
uint16 reserved_sectors;
uint8 num_of_fats;
tFatType fat_type;
// Disk/Media API
struct disk_if disk_io;
// [Optional] Thread Safety
void (*fl_lock)(void);
void (*fl_unlock)(void);
// Working buffer
struct fat_buffer currentsector;
// FAT Buffer
struct fat_buffer *fat_buffer_head;
struct fat_buffer fat_buffers[FAT_BUFFERS];
};
struct fs_dir_list_status
{
uint32 sector;
uint32 cluster;
uint8 offset;
};
struct fs_dir_ent
{
char filename[FATFS_MAX_LONG_FILENAME];
uint8 is_dir;
uint32 cluster;
uint32 size;
#if FATFS_INC_TIME_DATE_SUPPORT
uint16 access_date;
uint16 write_time;
uint16 write_date;
uint16 create_date;
uint16 create_time;
#endif
};
//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
int fatfs_init(struct fatfs *fs);
uint32 fatfs_lba_of_cluster(struct fatfs *fs, uint32 Cluster_Number);
int fatfs_sector_reader(struct fatfs *fs, uint32 Startcluster, uint32 offset, uint8 *target);
int fatfs_sector_read(struct fatfs *fs, uint32 lba, uint8 *target, uint32 count);
int fatfs_sector_write(struct fatfs *fs, uint32 lba, uint8 *target, uint32 count);
int fatfs_read_sector(struct fatfs *fs, uint32 cluster, uint32 sector, uint8 *target);
int fatfs_write_sector(struct fatfs *fs, uint32 cluster, uint32 sector, uint8 *target);
void fatfs_show_details(struct fatfs *fs);
uint32 fatfs_get_root_cluster(struct fatfs *fs);
uint32 fatfs_get_file_entry(struct fatfs *fs, uint32 Cluster, char *nametofind, struct fat_dir_entry *sfEntry);
int fatfs_sfn_exists(struct fatfs *fs, uint32 Cluster, char *shortname);
int fatfs_update_file_length(struct fatfs *fs, uint32 Cluster, char *shortname, uint32 fileLength);
int fatfs_mark_file_deleted(struct fatfs *fs, uint32 Cluster, char *shortname);
void fatfs_list_directory_start(struct fatfs *fs, struct fs_dir_list_status *dirls, uint32 StartCluster);
int fatfs_list_directory_next(struct fatfs *fs, struct fs_dir_list_status *dirls, struct fs_dir_ent *entry);
int fatfs_update_timestamps(struct fat_dir_entry *directoryEntry, int create, int modify, int access);
#endif

View File

@@ -0,0 +1,91 @@
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// FAT16/32 File IO Library
// V2.6
// Ultra-Embedded.com
// Copyright 2003 - 2012
//
// Email: admin@ultra-embedded.com
//
// License: GPL
// If you would like a version with a more permissive license for use in
// closed source commercial applications please contact me for details.
//-----------------------------------------------------------------------------
//
// This file is part of FAT File IO Library.
//
// FAT File IO Library 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.
//
// FAT File IO 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with FAT File IO Library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#include <string.h>
#include "fat_cache.h"
// Per file cluster chain caching used to improve performance.
// This does not have to be enabled for architectures with low
// memory space.
//-----------------------------------------------------------------------------
// fatfs_cache_init:
//-----------------------------------------------------------------------------
int fatfs_cache_init(struct fatfs *fs, FL_FILE *file)
{
#ifdef FAT_CLUSTER_CACHE_ENTRIES
int i;
for (i=0;i<FAT_CLUSTER_CACHE_ENTRIES;i++)
{
file->cluster_cache_idx[i] = 0xFFFFFFFF; // Not used
file->cluster_cache_data[i] = 0;
}
#endif
return 1;
}
//-----------------------------------------------------------------------------
// fatfs_cache_get_next_cluster:
//-----------------------------------------------------------------------------
int fatfs_cache_get_next_cluster(struct fatfs *fs, FL_FILE *file, uint32 clusterIdx, uint32 *pNextCluster)
{
#ifdef FAT_CLUSTER_CACHE_ENTRIES
uint32 slot = clusterIdx % FAT_CLUSTER_CACHE_ENTRIES;
if (file->cluster_cache_idx[slot] == clusterIdx)
{
*pNextCluster = file->cluster_cache_data[slot];
return 1;
}
#endif
return 0;
}
//-----------------------------------------------------------------------------
// fatfs_cache_set_next_cluster:
//-----------------------------------------------------------------------------
int fatfs_cache_set_next_cluster(struct fatfs *fs, FL_FILE *file, uint32 clusterIdx, uint32 nextCluster)
{
#ifdef FAT_CLUSTER_CACHE_ENTRIES
uint32 slot = clusterIdx % FAT_CLUSTER_CACHE_ENTRIES;
if (file->cluster_cache_idx[slot] == clusterIdx)
file->cluster_cache_data[slot] = nextCluster;
else
{
file->cluster_cache_idx[slot] = clusterIdx;
file->cluster_cache_data[slot] = nextCluster;
}
#endif
return 1;
}

View File

@@ -0,0 +1,13 @@
#ifndef __FAT_CACHE_H__
#define __FAT_CACHE_H__
#include "fat_filelib.h"
//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
int fatfs_cache_init(struct fatfs *fs, FL_FILE *file);
int fatfs_cache_get_next_cluster(struct fatfs *fs, FL_FILE *file, uint32 clusterIdx, uint32 *pNextCluster);
int fatfs_cache_set_next_cluster(struct fatfs *fs, FL_FILE *file, uint32 clusterIdx, uint32 nextCluster);
#endif

View File

@@ -0,0 +1,128 @@
#ifndef __FAT_DEFS_H__
#define __FAT_DEFS_H__
#include "fat_opts.h"
#include "fat_types.h"
//-----------------------------------------------------------------------------
// FAT32 Offsets
// Name Offset
//-----------------------------------------------------------------------------
// Boot Sector
#define BS_JMPBOOT 0 // Length = 3
#define BS_OEMNAME 3 // Length = 8
#define BPB_BYTSPERSEC 11 // Length = 2
#define BPB_SECPERCLUS 13 // Length = 1
#define BPB_RSVDSECCNT 14 // Length = 2
#define BPB_NUMFATS 16 // Length = 1
#define BPB_ROOTENTCNT 17 // Length = 2
#define BPB_TOTSEC16 19 // Length = 2
#define BPB_MEDIA 21 // Length = 1
#define BPB_FATSZ16 22 // Length = 2
#define BPB_SECPERTRK 24 // Length = 2
#define BPB_NUMHEADS 26 // Length = 2
#define BPB_HIDDSEC 28 // Length = 4
#define BPB_TOTSEC32 32 // Length = 4
// FAT 12/16
#define BS_FAT_DRVNUM 36 // Length = 1
#define BS_FAT_BOOTSIG 38 // Length = 1
#define BS_FAT_VOLID 39 // Length = 4
#define BS_FAT_VOLLAB 43 // Length = 11
#define BS_FAT_FILSYSTYPE 54 // Length = 8
// FAT 32
#define BPB_FAT32_FATSZ32 36 // Length = 4
#define BPB_FAT32_EXTFLAGS 40 // Length = 2
#define BPB_FAT32_FSVER 42 // Length = 2
#define BPB_FAT32_ROOTCLUS 44 // Length = 4
#define BPB_FAT32_FSINFO 48 // Length = 2
#define BPB_FAT32_BKBOOTSEC 50 // Length = 2
#define BS_FAT32_DRVNUM 64 // Length = 1
#define BS_FAT32_BOOTSIG 66 // Length = 1
#define BS_FAT32_VOLID 67 // Length = 4
#define BS_FAT32_VOLLAB 71 // Length = 11
#define BS_FAT32_FILSYSTYPE 82 // Length = 8
//-----------------------------------------------------------------------------
// FAT Types
//-----------------------------------------------------------------------------
#define FAT_TYPE_FAT12 1
#define FAT_TYPE_FAT16 2
#define FAT_TYPE_FAT32 3
//-----------------------------------------------------------------------------
// FAT32 Specific Statics
//-----------------------------------------------------------------------------
#define SIGNATURE_POSITION 510
#define SIGNATURE_VALUE 0xAA55
#define PARTITION1_TYPECODE_LOCATION 450
#define FAT32_TYPECODE1 0x0B
#define FAT32_TYPECODE2 0x0C
#define PARTITION1_LBA_BEGIN_LOCATION 454
#define PARTITION1_SIZE_LOCATION 458
#define FAT_DIR_ENTRY_SIZE 32
#define FAT_SFN_SIZE_FULL 11
#define FAT_SFN_SIZE_PARTIAL 8
//-----------------------------------------------------------------------------
// FAT32 File Attributes and Types
//-----------------------------------------------------------------------------
#define FILE_ATTR_READ_ONLY 0x01
#define FILE_ATTR_HIDDEN 0x02
#define FILE_ATTR_SYSTEM 0x04
#define FILE_ATTR_SYSHID 0x06
#define FILE_ATTR_VOLUME_ID 0x08
#define FILE_ATTR_DIRECTORY 0x10
#define FILE_ATTR_ARCHIVE 0x20
#define FILE_ATTR_LFN_TEXT 0x0F
#define FILE_HEADER_BLANK 0x00
#define FILE_HEADER_DELETED 0xE5
#define FILE_TYPE_DIR 0x10
#define FILE_TYPE_FILE 0x20
//-----------------------------------------------------------------------------
// Time / Date details
//-----------------------------------------------------------------------------
#define FAT_TIME_HOURS_SHIFT 11
#define FAT_TIME_HOURS_MASK 0x1F
#define FAT_TIME_MINUTES_SHIFT 5
#define FAT_TIME_MINUTES_MASK 0x3F
#define FAT_TIME_SECONDS_SHIFT 0
#define FAT_TIME_SECONDS_MASK 0x1F
#define FAT_TIME_SECONDS_SCALE 2
#define FAT_DATE_YEAR_SHIFT 9
#define FAT_DATE_YEAR_MASK 0x7F
#define FAT_DATE_MONTH_SHIFT 5
#define FAT_DATE_MONTH_MASK 0xF
#define FAT_DATE_DAY_SHIFT 0
#define FAT_DATE_DAY_MASK 0x1F
#define FAT_DATE_YEAR_OFFSET 1980
//-----------------------------------------------------------------------------
// Other Defines
//-----------------------------------------------------------------------------
#define FAT32_LAST_CLUSTER 0xFFFFFFFF
#define FAT32_INVALID_CLUSTER 0xFFFFFFFF
STRUCT_PACK_BEGIN
struct fat_dir_entry STRUCT_PACK
{
uint8 Name[11];
uint8 Attr;
uint8 NTRes;
uint8 CrtTimeTenth;
uint8 CrtTime[2];
uint8 CrtDate[2];
uint8 LstAccDate[2];
uint16 FstClusHI;
uint8 WrtTime[2];
uint8 WrtDate[2];
uint16 FstClusLO;
uint32 FileSize;
} STRUCT_PACKED;
STRUCT_PACK_END
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,146 @@
#ifndef __FAT_FILELIB_H__
#define __FAT_FILELIB_H__
#include "fat_opts.h"
#include "fat_access.h"
#include "fat_list.h"
//-----------------------------------------------------------------------------
// Defines
//-----------------------------------------------------------------------------
#ifndef SEEK_CUR
#define SEEK_CUR 1
#endif
#ifndef SEEK_END
#define SEEK_END 2
#endif
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
#ifndef EOF
#define EOF (-1)
#endif
//-----------------------------------------------------------------------------
// Structures
//-----------------------------------------------------------------------------
struct sFL_FILE;
struct cluster_lookup
{
uint32 ClusterIdx;
uint32 CurrentCluster;
};
typedef struct sFL_FILE
{
uint32 parentcluster;
uint32 startcluster;
uint32 bytenum;
uint32 filelength;
int filelength_changed;
char path[FATFS_MAX_LONG_FILENAME];
char filename[FATFS_MAX_LONG_FILENAME];
uint8 shortfilename[11];
#ifdef FAT_CLUSTER_CACHE_ENTRIES
uint32 cluster_cache_idx[FAT_CLUSTER_CACHE_ENTRIES];
uint32 cluster_cache_data[FAT_CLUSTER_CACHE_ENTRIES];
#endif
// Cluster Lookup
struct cluster_lookup last_fat_lookup;
// Read/Write sector buffer
uint8 file_data_sector[FAT_SECTOR_SIZE];
uint32 file_data_address;
int file_data_dirty;
// File fopen flags
uint8 flags;
#define FILE_READ (1 << 0)
#define FILE_WRITE (1 << 1)
#define FILE_APPEND (1 << 2)
#define FILE_BINARY (1 << 3)
#define FILE_ERASE (1 << 4)
#define FILE_CREATE (1 << 5)
struct fat_node list_node;
} FL_FILE;
//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
// External
void fl_init(void);
void fl_attach_locks(void (*lock)(void), void (*unlock)(void));
int fl_attach_media(fn_diskio_read rd, fn_diskio_write wr);
void fl_shutdown(void);
// Standard API
void* fl_fopen(const char *path, const char *modifiers);
void fl_fclose(void *file);
int fl_fflush(void *file);
int fl_fgetc(void *file);
char * fl_fgets(char *s, int n, void *f);
int fl_fputc(int c, void *file);
int fl_fputs(const char * str, void *file);
int fl_fwrite(const void * data, int size, int count, void *file );
int fl_fread(void * data, int size, int count, void *file );
int fl_fseek(void *file , long offset , int origin );
int fl_fgetpos(void *file , uint32 * position);
long fl_ftell(void *f);
int fl_feof(void *f);
int fl_remove(const char * filename);
// Equivelant dirent.h
typedef struct fs_dir_list_status FL_DIR;
typedef struct fs_dir_ent fl_dirent;
FL_DIR* fl_opendir(const char* path, FL_DIR *dir);
int fl_readdir(FL_DIR *dirls, fl_dirent *entry);
int fl_closedir(FL_DIR* dir);
// Extensions
void fl_listdirectory(const char *path);
int fl_createdirectory(const char *path);
int fl_is_dir(const char *path);
int fl_format(uint32 volume_sectors, const char *name);
// Test hooks
#ifdef FATFS_INC_TEST_HOOKS
struct fatfs* fl_get_fs(void);
#endif
//-----------------------------------------------------------------------------
// Stdio file I/O names
//-----------------------------------------------------------------------------
#ifdef USE_FILELIB_STDIO_COMPAT_NAMES
#define FILE FL_FILE
#define fopen(a,b) fl_fopen(a, b)
#define fclose(a) fl_fclose(a)
#define fflush(a) fl_fflush(a)
#define fgetc(a) fl_fgetc(a)
#define fgets(a,b,c) fl_fgets(a, b, c)
#define fputc(a,b) fl_fputc(a, b)
#define fputs(a,b) fl_fputs(a, b)
#define fwrite(a,b,c,d) fl_fwrite(a, b, c, d)
#define fread(a,b,c,d) fl_fread(a, b, c, d)
#define fseek(a,b,c) fl_fseek(a, b, c)
#define fgetpos(a,b) fl_fgetpos(a, b)
#define ftell(a) fl_ftell(a)
#define feof(a) fl_feof(a)
#define remove(a) fl_remove(a)
#define mkdir(a) fl_createdirectory(a)
#define rmdir(a) 0
#endif
#endif

View File

@@ -0,0 +1,532 @@
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// FAT16/32 File IO Library
// V2.6
// Ultra-Embedded.com
// Copyright 2003 - 2012
//
// Email: admin@ultra-embedded.com
//
// License: GPL
// If you would like a version with a more permissive license for use in
// closed source commercial applications please contact me for details.
//-----------------------------------------------------------------------------
//
// This file is part of FAT File IO Library.
//
// FAT File IO Library 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.
//
// FAT File IO 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with FAT File IO Library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#include <string.h>
#include "fat_defs.h"
#include "fat_access.h"
#include "fat_table.h"
#include "fat_write.h"
#include "fat_string.h"
#include "fat_misc.h"
#include "fat_format.h"
#if FATFS_INC_FORMAT_SUPPORT
//-----------------------------------------------------------------------------
// Tables
//-----------------------------------------------------------------------------
struct sec_per_clus_table
{
uint32 sectors;
uint8 sectors_per_cluster;
};
struct sec_per_clus_table _cluster_size_table16[] =
{
{ 32680, 2}, // 16MB - 1K
{ 262144, 4}, // 128MB - 2K
{ 524288, 8}, // 256MB - 4K
{ 1048576, 16}, // 512MB - 8K
{ 2097152, 32}, // 1GB - 16K
{ 4194304, 64}, // 2GB - 32K
{ 8388608, 128},// 2GB - 64K [Warning only supported by Windows XP onwards]
{ 0 , 0 } // Invalid
};
struct sec_per_clus_table _cluster_size_table32[] =
{
{ 532480, 1}, // 260MB - 512b
{ 16777216, 8}, // 8GB - 4K
{ 33554432, 16}, // 16GB - 8K
{ 67108864, 32}, // 32GB - 16K
{ 0xFFFFFFFF, 64},// >32GB - 32K
{ 0 , 0 } // Invalid
};
//-----------------------------------------------------------------------------
// fatfs_calc_cluster_size: Calculate what cluster size should be used
//-----------------------------------------------------------------------------
static uint8 fatfs_calc_cluster_size(uint32 sectors, int is_fat32)
{
int i;
if (!is_fat32)
{
for (i=0; _cluster_size_table16[i].sectors_per_cluster != 0;i++)
if (sectors <= _cluster_size_table16[i].sectors)
return _cluster_size_table16[i].sectors_per_cluster;
}
else
{
for (i=0; _cluster_size_table32[i].sectors_per_cluster != 0;i++)
if (sectors <= _cluster_size_table32[i].sectors)
return _cluster_size_table32[i].sectors_per_cluster;
}
return 0;
}
//-----------------------------------------------------------------------------
// fatfs_erase_sectors: Erase a number of sectors
//-----------------------------------------------------------------------------
static int fatfs_erase_sectors(struct fatfs *fs, uint32 lba, int count)
{
int i;
// Zero sector first
memset(fs->currentsector.sector, 0, FAT_SECTOR_SIZE);
for (i=0;i<count;i++)
if (!fs->disk_io.write_media(lba + i, fs->currentsector.sector, 1))
return 0;
return 1;
}
//-----------------------------------------------------------------------------
// fatfs_create_boot_sector: Create the boot sector
//-----------------------------------------------------------------------------
static int fatfs_create_boot_sector(struct fatfs *fs, uint32 boot_sector_lba, uint32 vol_sectors, const char *name, int is_fat32)
{
uint32 total_clusters;
int i;
// Zero sector initially
memset(fs->currentsector.sector, 0, FAT_SECTOR_SIZE);
// OEM Name & Jump Code
fs->currentsector.sector[0] = 0xEB;
fs->currentsector.sector[1] = 0x3C;
fs->currentsector.sector[2] = 0x90;
fs->currentsector.sector[3] = 0x4D;
fs->currentsector.sector[4] = 0x53;
fs->currentsector.sector[5] = 0x44;
fs->currentsector.sector[6] = 0x4F;
fs->currentsector.sector[7] = 0x53;
fs->currentsector.sector[8] = 0x35;
fs->currentsector.sector[9] = 0x2E;
fs->currentsector.sector[10] = 0x30;
// Bytes per sector
fs->currentsector.sector[11] = (FAT_SECTOR_SIZE >> 0) & 0xFF;
fs->currentsector.sector[12] = (FAT_SECTOR_SIZE >> 8) & 0xFF;
// Get sectors per cluster size for the disk
fs->sectors_per_cluster = fatfs_calc_cluster_size(vol_sectors, is_fat32);
if (!fs->sectors_per_cluster)
return 0; // Invalid disk size
// Sectors per cluster
fs->currentsector.sector[13] = fs->sectors_per_cluster;
// Reserved Sectors
if (!is_fat32)
fs->reserved_sectors = 8;
else
fs->reserved_sectors = 32;
fs->currentsector.sector[14] = (fs->reserved_sectors >> 0) & 0xFF;
fs->currentsector.sector[15] = (fs->reserved_sectors >> 8) & 0xFF;
// Number of FATS
fs->num_of_fats = 2;
fs->currentsector.sector[16] = fs->num_of_fats;
// Max entries in root dir (FAT16 only)
if (!is_fat32)
{
fs->root_entry_count = 512;
fs->currentsector.sector[17] = (fs->root_entry_count >> 0) & 0xFF;
fs->currentsector.sector[18] = (fs->root_entry_count >> 8) & 0xFF;
}
else
{
fs->root_entry_count = 0;
fs->currentsector.sector[17] = 0;
fs->currentsector.sector[18] = 0;
}
// [FAT16] Total sectors (use FAT32 count instead)
fs->currentsector.sector[19] = 0x00;
fs->currentsector.sector[20] = 0x00;
// Media type
fs->currentsector.sector[21] = 0xF8;
// FAT16 BS Details
if (!is_fat32)
{
// Count of sectors used by the FAT table (FAT16 only)
total_clusters = (vol_sectors / fs->sectors_per_cluster) + 1;
fs->fat_sectors = (total_clusters/(FAT_SECTOR_SIZE/2)) + 1;
fs->currentsector.sector[22] = (uint8)((fs->fat_sectors >> 0) & 0xFF);
fs->currentsector.sector[23] = (uint8)((fs->fat_sectors >> 8) & 0xFF);
// Sectors per track
fs->currentsector.sector[24] = 0x00;
fs->currentsector.sector[25] = 0x00;
// Heads
fs->currentsector.sector[26] = 0x00;
fs->currentsector.sector[27] = 0x00;
// Hidden sectors
fs->currentsector.sector[28] = 0x20;
fs->currentsector.sector[29] = 0x00;
fs->currentsector.sector[30] = 0x00;
fs->currentsector.sector[31] = 0x00;
// Total sectors for this volume
fs->currentsector.sector[32] = (uint8)((vol_sectors>>0)&0xFF);
fs->currentsector.sector[33] = (uint8)((vol_sectors>>8)&0xFF);
fs->currentsector.sector[34] = (uint8)((vol_sectors>>16)&0xFF);
fs->currentsector.sector[35] = (uint8)((vol_sectors>>24)&0xFF);
// Drive number
fs->currentsector.sector[36] = 0x00;
// Reserved
fs->currentsector.sector[37] = 0x00;
// Boot signature
fs->currentsector.sector[38] = 0x29;
// Volume ID
fs->currentsector.sector[39] = 0x12;
fs->currentsector.sector[40] = 0x34;
fs->currentsector.sector[41] = 0x56;
fs->currentsector.sector[42] = 0x78;
// Volume name
for (i=0;i<11;i++)
{
if (i < (int)strlen(name))
fs->currentsector.sector[i+43] = name[i];
else
fs->currentsector.sector[i+43] = ' ';
}
// File sys type
fs->currentsector.sector[54] = 'F';
fs->currentsector.sector[55] = 'A';
fs->currentsector.sector[56] = 'T';
fs->currentsector.sector[57] = '1';
fs->currentsector.sector[58] = '6';
fs->currentsector.sector[59] = ' ';
fs->currentsector.sector[60] = ' ';
fs->currentsector.sector[61] = ' ';
// Signature
fs->currentsector.sector[510] = 0x55;
fs->currentsector.sector[511] = 0xAA;
}
// FAT32 BS Details
else
{
// Count of sectors used by the FAT table (FAT16 only)
fs->currentsector.sector[22] = 0;
fs->currentsector.sector[23] = 0;
// Sectors per track (default)
fs->currentsector.sector[24] = 0x3F;
fs->currentsector.sector[25] = 0x00;
// Heads (default)
fs->currentsector.sector[26] = 0xFF;
fs->currentsector.sector[27] = 0x00;
// Hidden sectors
fs->currentsector.sector[28] = 0x00;
fs->currentsector.sector[29] = 0x00;
fs->currentsector.sector[30] = 0x00;
fs->currentsector.sector[31] = 0x00;
// Total sectors for this volume
fs->currentsector.sector[32] = (uint8)((vol_sectors>>0)&0xFF);
fs->currentsector.sector[33] = (uint8)((vol_sectors>>8)&0xFF);
fs->currentsector.sector[34] = (uint8)((vol_sectors>>16)&0xFF);
fs->currentsector.sector[35] = (uint8)((vol_sectors>>24)&0xFF);
total_clusters = (vol_sectors / fs->sectors_per_cluster) + 1;
fs->fat_sectors = (total_clusters/(FAT_SECTOR_SIZE/4)) + 1;
// BPB_FATSz32
fs->currentsector.sector[36] = (uint8)((fs->fat_sectors>>0)&0xFF);
fs->currentsector.sector[37] = (uint8)((fs->fat_sectors>>8)&0xFF);
fs->currentsector.sector[38] = (uint8)((fs->fat_sectors>>16)&0xFF);
fs->currentsector.sector[39] = (uint8)((fs->fat_sectors>>24)&0xFF);
// BPB_ExtFlags
fs->currentsector.sector[40] = 0;
fs->currentsector.sector[41] = 0;
// BPB_FSVer
fs->currentsector.sector[42] = 0;
fs->currentsector.sector[43] = 0;
// BPB_RootClus
fs->currentsector.sector[44] = (uint8)((fs->rootdir_first_cluster>>0)&0xFF);
fs->currentsector.sector[45] = (uint8)((fs->rootdir_first_cluster>>8)&0xFF);
fs->currentsector.sector[46] = (uint8)((fs->rootdir_first_cluster>>16)&0xFF);
fs->currentsector.sector[47] = (uint8)((fs->rootdir_first_cluster>>24)&0xFF);
// BPB_FSInfo
fs->currentsector.sector[48] = (uint8)((fs->fs_info_sector>>0)&0xFF);
fs->currentsector.sector[49] = (uint8)((fs->fs_info_sector>>8)&0xFF);
// BPB_BkBootSec
fs->currentsector.sector[50] = 6;
fs->currentsector.sector[51] = 0;
// Drive number
fs->currentsector.sector[64] = 0x00;
// Boot signature
fs->currentsector.sector[66] = 0x29;
// Volume ID
fs->currentsector.sector[67] = 0x12;
fs->currentsector.sector[68] = 0x34;
fs->currentsector.sector[69] = 0x56;
fs->currentsector.sector[70] = 0x78;
// Volume name
for (i=0;i<11;i++)
{
if (i < (int)strlen(name))
fs->currentsector.sector[i+71] = name[i];
else
fs->currentsector.sector[i+71] = ' ';
}
// File sys type
fs->currentsector.sector[82] = 'F';
fs->currentsector.sector[83] = 'A';
fs->currentsector.sector[84] = 'T';
fs->currentsector.sector[85] = '3';
fs->currentsector.sector[86] = '2';
fs->currentsector.sector[87] = ' ';
fs->currentsector.sector[88] = ' ';
fs->currentsector.sector[89] = ' ';
// Signature
fs->currentsector.sector[510] = 0x55;
fs->currentsector.sector[511] = 0xAA;
}
if (fs->disk_io.write_media(boot_sector_lba, fs->currentsector.sector, 1))
return 1;
else
return 0;
}
//-----------------------------------------------------------------------------
// fatfs_create_fsinfo_sector: Create the FSInfo sector (FAT32)
//-----------------------------------------------------------------------------
static int fatfs_create_fsinfo_sector(struct fatfs *fs, uint32 sector_lba)
{
// Zero sector initially
memset(fs->currentsector.sector, 0, FAT_SECTOR_SIZE);
// FSI_LeadSig
fs->currentsector.sector[0] = 0x52;
fs->currentsector.sector[1] = 0x52;
fs->currentsector.sector[2] = 0x61;
fs->currentsector.sector[3] = 0x41;
// FSI_StrucSig
fs->currentsector.sector[484] = 0x72;
fs->currentsector.sector[485] = 0x72;
fs->currentsector.sector[486] = 0x41;
fs->currentsector.sector[487] = 0x61;
// FSI_Free_Count
fs->currentsector.sector[488] = 0xFF;
fs->currentsector.sector[489] = 0xFF;
fs->currentsector.sector[490] = 0xFF;
fs->currentsector.sector[491] = 0xFF;
// FSI_Nxt_Free
fs->currentsector.sector[492] = 0xFF;
fs->currentsector.sector[493] = 0xFF;
fs->currentsector.sector[494] = 0xFF;
fs->currentsector.sector[495] = 0xFF;
// Signature
fs->currentsector.sector[510] = 0x55;
fs->currentsector.sector[511] = 0xAA;
if (fs->disk_io.write_media(sector_lba, fs->currentsector.sector, 1))
return 1;
else
return 0;
}
//-----------------------------------------------------------------------------
// fatfs_erase_fat: Erase FAT table using fs details in fs struct
//-----------------------------------------------------------------------------
static int fatfs_erase_fat(struct fatfs *fs, int is_fat32)
{
uint32 i;
// Zero sector initially
memset(fs->currentsector.sector, 0, FAT_SECTOR_SIZE);
// Initialise default allocate / reserved clusters
if (!is_fat32)
{
SET_16BIT_WORD(fs->currentsector.sector, 0, 0xFFF8);
SET_16BIT_WORD(fs->currentsector.sector, 2, 0xFFFF);
}
else
{
SET_32BIT_WORD(fs->currentsector.sector, 0, 0x0FFFFFF8);
SET_32BIT_WORD(fs->currentsector.sector, 4, 0xFFFFFFFF);
SET_32BIT_WORD(fs->currentsector.sector, 8, 0x0FFFFFFF);
}
if (!fs->disk_io.write_media(fs->fat_begin_lba + 0, fs->currentsector.sector, 1))
return 0;
// Zero remaining FAT sectors
memset(fs->currentsector.sector, 0, FAT_SECTOR_SIZE);
for (i=1;i<fs->fat_sectors*fs->num_of_fats;i++)
if (!fs->disk_io.write_media(fs->fat_begin_lba + i, fs->currentsector.sector, 1))
return 0;
return 1;
}
//-----------------------------------------------------------------------------
// fatfs_format_fat16: Format a FAT16 partition
//-----------------------------------------------------------------------------
int fatfs_format_fat16(struct fatfs *fs, uint32 volume_sectors, const char *name)
{
fs->currentsector.address = FAT32_INVALID_CLUSTER;
fs->currentsector.dirty = 0;
fs->next_free_cluster = 0; // Invalid
fatfs_fat_init(fs);
// Make sure we have read + write functions
if (!fs->disk_io.read_media || !fs->disk_io.write_media)
return FAT_INIT_MEDIA_ACCESS_ERROR;
// Volume is FAT16
fs->fat_type = FAT_TYPE_16;
// Not valid for FAT16
fs->fs_info_sector = 0;
fs->rootdir_first_cluster = 0;
// Sector 0: Boot sector
// NOTE: We don't need an MBR, it is a waste of a good sector!
fs->lba_begin = 0;
if (!fatfs_create_boot_sector(fs, fs->lba_begin, volume_sectors, name, 0))
return 0;
// For FAT16 (which this may be), rootdir_first_cluster is actuall rootdir_first_sector
fs->rootdir_first_sector = fs->reserved_sectors + (fs->num_of_fats * fs->fat_sectors);
fs->rootdir_sectors = ((fs->root_entry_count * 32) + (FAT_SECTOR_SIZE - 1)) / FAT_SECTOR_SIZE;
// First FAT LBA address
fs->fat_begin_lba = fs->lba_begin + fs->reserved_sectors;
// The address of the first data cluster on this volume
fs->cluster_begin_lba = fs->fat_begin_lba + (fs->num_of_fats * fs->fat_sectors);
// Initialise FAT sectors
if (!fatfs_erase_fat(fs, 0))
return 0;
// Erase Root directory
if (!fatfs_erase_sectors(fs, fs->lba_begin + fs->rootdir_first_sector, fs->rootdir_sectors))
return 0;
return 1;
}
//-----------------------------------------------------------------------------
// fatfs_format_fat32: Format a FAT32 partition
//-----------------------------------------------------------------------------
int fatfs_format_fat32(struct fatfs *fs, uint32 volume_sectors, const char *name)
{
fs->currentsector.address = FAT32_INVALID_CLUSTER;
fs->currentsector.dirty = 0;
fs->next_free_cluster = 0; // Invalid
fatfs_fat_init(fs);
// Make sure we have read + write functions
if (!fs->disk_io.read_media || !fs->disk_io.write_media)
return FAT_INIT_MEDIA_ACCESS_ERROR;
// Volume is FAT32
fs->fat_type = FAT_TYPE_32;
// Basic defaults for normal FAT32 partitions
fs->fs_info_sector = 1;
fs->rootdir_first_cluster = 2;
// Sector 0: Boot sector
// NOTE: We don't need an MBR, it is a waste of a good sector!
fs->lba_begin = 0;
if (!fatfs_create_boot_sector(fs, fs->lba_begin, volume_sectors, name, 1))
return 0;
// First FAT LBA address
fs->fat_begin_lba = fs->lba_begin + fs->reserved_sectors;
// The address of the first data cluster on this volume
fs->cluster_begin_lba = fs->fat_begin_lba + (fs->num_of_fats * fs->fat_sectors);
// Initialise FSInfo sector
if (!fatfs_create_fsinfo_sector(fs, fs->fs_info_sector))
return 0;
// Initialise FAT sectors
if (!fatfs_erase_fat(fs, 1))
return 0;
// Erase Root directory
if (!fatfs_erase_sectors(fs, fatfs_lba_of_cluster(fs, fs->rootdir_first_cluster), fs->sectors_per_cluster))
return 0;
return 1;
}
//-----------------------------------------------------------------------------
// fatfs_format: Format a partition with either FAT16 or FAT32 based on size
//-----------------------------------------------------------------------------
int fatfs_format(struct fatfs *fs, uint32 volume_sectors, const char *name)
{
// 2GB - 32K limit for safe behaviour for FAT16
if (volume_sectors <= 4194304)
return fatfs_format_fat16(fs, volume_sectors, name);
else
return fatfs_format_fat32(fs, volume_sectors, name);
}
#endif /*FATFS_INC_FORMAT_SUPPORT*/

View File

@@ -0,0 +1,15 @@
#ifndef __FAT_FORMAT_H__
#define __FAT_FORMAT_H__
#include "fat_defs.h"
#include "fat_opts.h"
#include "fat_access.h"
//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
int fatfs_format(struct fatfs *fs, uint32 volume_sectors, const char *name);
int fatfs_format_fat16(struct fatfs *fs, uint32 volume_sectors, const char *name);
int fatfs_format_fat32(struct fatfs *fs, uint32 volume_sectors, const char *name);
#endif

View File

@@ -0,0 +1,161 @@
#ifndef __FAT_LIST_H__
#define __FAT_LIST_H__
#ifndef FAT_ASSERT
#define FAT_ASSERT(x)
#endif
#ifndef FAT_INLINE
#define FAT_INLINE
#endif
//-----------------------------------------------------------------
// Types
//-----------------------------------------------------------------
struct fat_list;
struct fat_node
{
struct fat_node *previous;
struct fat_node *next;
};
struct fat_list
{
struct fat_node *head;
struct fat_node *tail;
};
//-----------------------------------------------------------------
// Macros
//-----------------------------------------------------------------
#define fat_list_entry(p, t, m) p ? ((t *)((char *)(p)-(char*)(&((t *)0)->m))) : 0
#define fat_list_next(l, p) (p)->next
#define fat_list_prev(l, p) (p)->previous
#define fat_list_first(l) (l)->head
#define fat_list_last(l) (l)->tail
#define fat_list_for_each(l, p) for ((p) = (l)->head; (p); (p) = (p)->next)
//-----------------------------------------------------------------
// Inline Functions
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// fat_list_init:
//-----------------------------------------------------------------
static FAT_INLINE void fat_list_init(struct fat_list *list)
{
FAT_ASSERT(list);
list->head = list->tail = 0;
}
//-----------------------------------------------------------------
// fat_list_remove:
//-----------------------------------------------------------------
static FAT_INLINE void fat_list_remove(struct fat_list *list, struct fat_node *node)
{
FAT_ASSERT(list);
FAT_ASSERT(node);
if(!node->previous)
list->head = node->next;
else
node->previous->next = node->next;
if(!node->next)
list->tail = node->previous;
else
node->next->previous = node->previous;
}
//-----------------------------------------------------------------
// fat_list_insert_after:
//-----------------------------------------------------------------
static FAT_INLINE void fat_list_insert_after(struct fat_list *list, struct fat_node *node, struct fat_node *new_node)
{
FAT_ASSERT(list);
FAT_ASSERT(node);
FAT_ASSERT(new_node);
new_node->previous = node;
new_node->next = node->next;
if (!node->next)
list->tail = new_node;
else
node->next->previous = new_node;
node->next = new_node;
}
//-----------------------------------------------------------------
// fat_list_insert_before:
//-----------------------------------------------------------------
static FAT_INLINE void fat_list_insert_before(struct fat_list *list, struct fat_node *node, struct fat_node *new_node)
{
FAT_ASSERT(list);
FAT_ASSERT(node);
FAT_ASSERT(new_node);
new_node->previous = node->previous;
new_node->next = node;
if (!node->previous)
list->head = new_node;
else
node->previous->next = new_node;
node->previous = new_node;
}
//-----------------------------------------------------------------
// fat_list_insert_first:
//-----------------------------------------------------------------
static FAT_INLINE void fat_list_insert_first(struct fat_list *list, struct fat_node *node)
{
FAT_ASSERT(list);
FAT_ASSERT(node);
if (!list->head)
{
list->head = node;
list->tail = node;
node->previous = 0;
node->next = 0;
}
else
fat_list_insert_before(list, list->head, node);
}
//-----------------------------------------------------------------
// fat_list_insert_last:
//-----------------------------------------------------------------
static FAT_INLINE void fat_list_insert_last(struct fat_list *list, struct fat_node *node)
{
FAT_ASSERT(list);
FAT_ASSERT(node);
if (!list->tail)
fat_list_insert_first(list, node);
else
fat_list_insert_after(list, list->tail, node);
}
//-----------------------------------------------------------------
// fat_list_is_empty:
//-----------------------------------------------------------------
static FAT_INLINE int fat_list_is_empty(struct fat_list *list)
{
FAT_ASSERT(list);
return !list->head;
}
//-----------------------------------------------------------------
// fat_list_pop_head:
//-----------------------------------------------------------------
static FAT_INLINE struct fat_node * fat_list_pop_head(struct fat_list *list)
{
struct fat_node * node;
FAT_ASSERT(list);
node = fat_list_first(list);
if (node)
fat_list_remove(list, node);
return node;
}
#endif

View File

@@ -0,0 +1,505 @@
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// FAT16/32 File IO Library
// V2.6
// Ultra-Embedded.com
// Copyright 2003 - 2012
//
// Email: admin@ultra-embedded.com
//
// License: GPL
// If you would like a version with a more permissive license for use in
// closed source commercial applications please contact me for details.
//-----------------------------------------------------------------------------
//
// This file is part of FAT File IO Library.
//
// FAT File IO Library 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.
//
// FAT File IO 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with FAT File IO Library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#include <stdlib.h>
#include <string.h>
#include "fat_misc.h"
//-----------------------------------------------------------------------------
// fatfs_lfn_cache_init: Clear long file name cache
//-----------------------------------------------------------------------------
void fatfs_lfn_cache_init(struct lfn_cache *lfn, int wipeTable)
{
int i = 0;
lfn->no_of_strings = 0;
#if FATFS_INC_LFN_SUPPORT
// Zero out buffer also
if (wipeTable)
for (i=0;i<MAX_LONGFILENAME_ENTRIES;i++)
memset(lfn->String[i], 0x00, MAX_LFN_ENTRY_LENGTH);
#endif
}
//-----------------------------------------------------------------------------
// fatfs_lfn_cache_entry - Function extracts long file name text from sector
// at a specific offset
//-----------------------------------------------------------------------------
#if FATFS_INC_LFN_SUPPORT
void fatfs_lfn_cache_entry(struct lfn_cache *lfn, uint8 *entryBuffer)
{
uint8 LFNIndex, i;
LFNIndex = entryBuffer[0] & 0x1F;
// Limit file name to cache size!
if (LFNIndex > MAX_LONGFILENAME_ENTRIES)
return ;
// This is an error condition
if (LFNIndex == 0)
return ;
if (lfn->no_of_strings == 0)
lfn->no_of_strings = LFNIndex;
lfn->String[LFNIndex-1][0] = entryBuffer[1];
lfn->String[LFNIndex-1][1] = entryBuffer[3];
lfn->String[LFNIndex-1][2] = entryBuffer[5];
lfn->String[LFNIndex-1][3] = entryBuffer[7];
lfn->String[LFNIndex-1][4] = entryBuffer[9];
lfn->String[LFNIndex-1][5] = entryBuffer[0x0E];
lfn->String[LFNIndex-1][6] = entryBuffer[0x10];
lfn->String[LFNIndex-1][7] = entryBuffer[0x12];
lfn->String[LFNIndex-1][8] = entryBuffer[0x14];
lfn->String[LFNIndex-1][9] = entryBuffer[0x16];
lfn->String[LFNIndex-1][10] = entryBuffer[0x18];
lfn->String[LFNIndex-1][11] = entryBuffer[0x1C];
lfn->String[LFNIndex-1][12] = entryBuffer[0x1E];
for (i=0; i<MAX_LFN_ENTRY_LENGTH; i++)
if (lfn->String[LFNIndex-1][i]==0xFF)
lfn->String[LFNIndex-1][i] = 0x20; // Replace with spaces
}
#endif
//-----------------------------------------------------------------------------
// fatfs_lfn_cache_get: Get a reference to the long filename
//-----------------------------------------------------------------------------
#if FATFS_INC_LFN_SUPPORT
char* fatfs_lfn_cache_get(struct lfn_cache *lfn)
{
// Null terminate long filename
if (lfn->no_of_strings == MAX_LONGFILENAME_ENTRIES)
lfn->Null = '\0';
else if (lfn->no_of_strings)
lfn->String[lfn->no_of_strings][0] = '\0';
else
lfn->String[0][0] = '\0';
return (char*)&lfn->String[0][0];
}
#endif
//-----------------------------------------------------------------------------
// fatfs_entry_lfn_text: If LFN text entry found
//-----------------------------------------------------------------------------
#if FATFS_INC_LFN_SUPPORT
int fatfs_entry_lfn_text(struct fat_dir_entry *entry)
{
if ((entry->Attr & FILE_ATTR_LFN_TEXT) == FILE_ATTR_LFN_TEXT)
return 1;
else
return 0;
}
#endif
//-----------------------------------------------------------------------------
// fatfs_entry_lfn_invalid: If SFN found not relating to LFN
//-----------------------------------------------------------------------------
#if FATFS_INC_LFN_SUPPORT
int fatfs_entry_lfn_invalid(struct fat_dir_entry *entry)
{
if ( (entry->Name[0]==FILE_HEADER_BLANK) ||
(entry->Name[0]==FILE_HEADER_DELETED)||
(entry->Attr==FILE_ATTR_VOLUME_ID) ||
(entry->Attr & FILE_ATTR_SYSHID) )
return 1;
else
return 0;
}
#endif
//-----------------------------------------------------------------------------
// fatfs_entry_lfn_exists: If LFN exists and correlation SFN found
//-----------------------------------------------------------------------------
#if FATFS_INC_LFN_SUPPORT
int fatfs_entry_lfn_exists(struct lfn_cache *lfn, struct fat_dir_entry *entry)
{
if ( (entry->Attr!=FILE_ATTR_LFN_TEXT) &&
(entry->Name[0]!=FILE_HEADER_BLANK) &&
(entry->Name[0]!=FILE_HEADER_DELETED) &&
(entry->Attr!=FILE_ATTR_VOLUME_ID) &&
(!(entry->Attr&FILE_ATTR_SYSHID)) &&
(lfn->no_of_strings) )
return 1;
else
return 0;
}
#endif
//-----------------------------------------------------------------------------
// fatfs_entry_sfn_only: If SFN only exists
//-----------------------------------------------------------------------------
int fatfs_entry_sfn_only(struct fat_dir_entry *entry)
{
if ( (entry->Attr!=FILE_ATTR_LFN_TEXT) &&
(entry->Name[0]!=FILE_HEADER_BLANK) &&
(entry->Name[0]!=FILE_HEADER_DELETED) &&
(entry->Attr!=FILE_ATTR_VOLUME_ID) &&
(!(entry->Attr&FILE_ATTR_SYSHID)) )
return 1;
else
return 0;
}
// TODO: FILE_ATTR_SYSHID ?!?!??!
//-----------------------------------------------------------------------------
// fatfs_entry_is_dir: Returns 1 if a directory
//-----------------------------------------------------------------------------
int fatfs_entry_is_dir(struct fat_dir_entry *entry)
{
if (entry->Attr & FILE_TYPE_DIR)
return 1;
else
return 0;
}
//-----------------------------------------------------------------------------
// fatfs_entry_is_file: Returns 1 is a file entry
//-----------------------------------------------------------------------------
int fatfs_entry_is_file(struct fat_dir_entry *entry)
{
if (entry->Attr & FILE_TYPE_FILE)
return 1;
else
return 0;
}
//-----------------------------------------------------------------------------
// fatfs_lfn_entries_required: Calculate number of 13 characters entries
//-----------------------------------------------------------------------------
#if FATFS_INC_LFN_SUPPORT
int fatfs_lfn_entries_required(char *filename)
{
int length = (int)strlen(filename);
if (length)
return (length + MAX_LFN_ENTRY_LENGTH - 1) / MAX_LFN_ENTRY_LENGTH;
else
return 0;
}
#endif
//-----------------------------------------------------------------------------
// fatfs_filename_to_lfn:
//-----------------------------------------------------------------------------
#if FATFS_INC_LFN_SUPPORT
void fatfs_filename_to_lfn(char *filename, uint8 *buffer, int entry, uint8 sfnChk)
{
int i;
int nameIndexes[MAX_LFN_ENTRY_LENGTH] = {1,3,5,7,9,0x0E,0x10,0x12,0x14,0x16,0x18,0x1C,0x1E};
// 13 characters entries
int length = (int)strlen(filename);
int entriesRequired = fatfs_lfn_entries_required(filename);
// Filename offset
int start = entry * MAX_LFN_ENTRY_LENGTH;
// Initialise to zeros
memset(buffer, 0x00, FAT_DIR_ENTRY_SIZE);
// LFN entry number
buffer[0] = (uint8)(((entriesRequired-1)==entry)?(0x40|(entry+1)):(entry+1));
// LFN flag
buffer[11] = 0x0F;
// Checksum of short filename
buffer[13] = sfnChk;
// Copy to buffer
for (i=0;i<MAX_LFN_ENTRY_LENGTH;i++)
{
if ( (start+i) < length )
buffer[nameIndexes[i]] = filename[start+i];
else if ( (start+i) == length )
buffer[nameIndexes[i]] = 0x00;
else
{
buffer[nameIndexes[i]] = 0xFF;
buffer[nameIndexes[i]+1] = 0xFF;
}
}
}
#endif
//-----------------------------------------------------------------------------
// fatfs_sfn_create_entry: Create the short filename directory entry
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
void fatfs_sfn_create_entry(char *shortfilename, uint32 size, uint32 startCluster, struct fat_dir_entry *entry, int dir)
{
int i;
// Copy short filename
for (i=0;i<FAT_SFN_SIZE_FULL;i++)
entry->Name[i] = shortfilename[i];
// Unless we have a RTC we might as well set these to 1980
entry->CrtTimeTenth = 0x00;
entry->CrtTime[1] = entry->CrtTime[0] = 0x00;
entry->CrtDate[1] = 0x00;
entry->CrtDate[0] = 0x20;
entry->LstAccDate[1] = 0x00;
entry->LstAccDate[0] = 0x20;
entry->WrtTime[1] = entry->WrtTime[0] = 0x00;
entry->WrtDate[1] = 0x00;
entry->WrtDate[0] = 0x20;
if (!dir)
entry->Attr = FILE_TYPE_FILE;
else
entry->Attr = FILE_TYPE_DIR;
entry->NTRes = 0x00;
entry->FstClusHI = FAT_HTONS((uint16)((startCluster>>16) & 0xFFFF));
entry->FstClusLO = FAT_HTONS((uint16)((startCluster>>0) & 0xFFFF));
entry->FileSize = FAT_HTONL(size);
}
#endif
//-----------------------------------------------------------------------------
// fatfs_lfn_create_sfn: Create a padded SFN
//-----------------------------------------------------------------------------
#if FATFS_INC_WRITE_SUPPORT
int fatfs_lfn_create_sfn(char *sfn_output, char *filename)
{
int i;
int dotPos = -1;
char ext[3];
int pos;
int len = (int)strlen(filename);
// Invalid to start with .
if (filename[0]=='.')
return 0;
memset(sfn_output, ' ', FAT_SFN_SIZE_FULL);
memset(ext, ' ', 3);
// Find dot seperator
for (i = 0; i< len; i++)
{
if (filename[i]=='.')
dotPos = i;
}
// Extract extensions
if (dotPos!=-1)
{
// Copy first three chars of extension
for (i = (dotPos+1); i < (dotPos+1+3); i++)
if (i<len)
ext[i-(dotPos+1)] = filename[i];
// Shorten the length to the dot position
len = dotPos;
}
// Add filename part
pos = 0;
for (i=0;i<len;i++)
{
if ( (filename[i]!=' ') && (filename[i]!='.') )
{
if (filename[i] >= 'a' && filename[i] <= 'z')
sfn_output[pos++] = filename[i] - 'a' + 'A';
else
sfn_output[pos++] = filename[i];
}
// Fill upto 8 characters
if (pos==FAT_SFN_SIZE_PARTIAL)
break;
}
// Add extension part
for (i=FAT_SFN_SIZE_PARTIAL;i<FAT_SFN_SIZE_FULL;i++)
{
if (ext[i-FAT_SFN_SIZE_PARTIAL] >= 'a' && ext[i-FAT_SFN_SIZE_PARTIAL] <= 'z')
sfn_output[i] = ext[i-FAT_SFN_SIZE_PARTIAL] - 'a' + 'A';
else
sfn_output[i] = ext[i-FAT_SFN_SIZE_PARTIAL];
}
return 1;
}
//-----------------------------------------------------------------------------
// fatfs_itoa:
//-----------------------------------------------------------------------------
static void fatfs_itoa(uint32 num, char *s)
{
char* cp;
char outbuf[12];
const char digits[] = "0123456789ABCDEF";
// Build string backwards
cp = outbuf;
do
{
*cp++ = digits[(int)(num % 10)];
}
while ((num /= 10) > 0);
*cp-- = 0;
// Copy in forwards
while (cp >= outbuf)
*s++ = *cp--;
*s = 0;
}
#endif
//-----------------------------------------------------------------------------
// fatfs_lfn_generate_tail:
// sfn_input = Input short filename, spaced format & in upper case
// sfn_output = Output short filename with tail
//-----------------------------------------------------------------------------
#if FATFS_INC_LFN_SUPPORT
#if FATFS_INC_WRITE_SUPPORT
int fatfs_lfn_generate_tail(char *sfn_output, char *sfn_input, uint32 tailNum)
{
int tail_chars;
char tail_str[12];
if (tailNum > 99999)
return 0;
// Convert to number
memset(tail_str, 0x00, sizeof(tail_str));
tail_str[0] = '~';
fatfs_itoa(tailNum, tail_str+1);
// Copy in base filename
memcpy(sfn_output, sfn_input, FAT_SFN_SIZE_FULL);
// Overwrite with tail
tail_chars = (int)strlen(tail_str);
memcpy(sfn_output+(FAT_SFN_SIZE_PARTIAL-tail_chars), tail_str, tail_chars);
return 1;
}
#endif
#endif
//-----------------------------------------------------------------------------
// fatfs_convert_from_fat_time: Convert FAT time to h/m/s
//-----------------------------------------------------------------------------
#if FATFS_INC_TIME_DATE_SUPPORT
void fatfs_convert_from_fat_time(uint16 fat_time, int *hours, int *minutes, int *seconds)
{
*hours = (fat_time >> FAT_TIME_HOURS_SHIFT) & FAT_TIME_HOURS_MASK;
*minutes = (fat_time >> FAT_TIME_MINUTES_SHIFT) & FAT_TIME_MINUTES_MASK;
*seconds = (fat_time >> FAT_TIME_SECONDS_SHIFT) & FAT_TIME_SECONDS_MASK;
*seconds = *seconds * FAT_TIME_SECONDS_SCALE;
}
//-----------------------------------------------------------------------------
// fatfs_convert_from_fat_date: Convert FAT date to d/m/y
//-----------------------------------------------------------------------------
void fatfs_convert_from_fat_date(uint16 fat_date, int *day, int *month, int *year)
{
*day = (fat_date >> FAT_DATE_DAY_SHIFT) & FAT_DATE_DAY_MASK;
*month = (fat_date >> FAT_DATE_MONTH_SHIFT) & FAT_DATE_MONTH_MASK;
*year = (fat_date >> FAT_DATE_YEAR_SHIFT) & FAT_DATE_YEAR_MASK;
*year = *year + FAT_DATE_YEAR_OFFSET;
}
//-----------------------------------------------------------------------------
// fatfs_convert_to_fat_time: Convert h/m/s to FAT time
//-----------------------------------------------------------------------------
uint16 fatfs_convert_to_fat_time(int hours, int minutes, int seconds)
{
uint16 fat_time = 0;
// Most FAT times are to a resolution of 2 seconds
seconds /= FAT_TIME_SECONDS_SCALE;
fat_time = (hours & FAT_TIME_HOURS_MASK) << FAT_TIME_HOURS_SHIFT;
fat_time|= (minutes & FAT_TIME_MINUTES_MASK) << FAT_TIME_MINUTES_SHIFT;
fat_time|= (seconds & FAT_TIME_SECONDS_MASK) << FAT_TIME_SECONDS_SHIFT;
return fat_time;
}
//-----------------------------------------------------------------------------
// fatfs_convert_to_fat_date: Convert d/m/y to FAT date
//-----------------------------------------------------------------------------
uint16 fatfs_convert_to_fat_date(int day, int month, int year)
{
uint16 fat_date = 0;
// FAT dates are relative to 1980
if (year >= FAT_DATE_YEAR_OFFSET)
year -= FAT_DATE_YEAR_OFFSET;
fat_date = (day & FAT_DATE_DAY_MASK) << FAT_DATE_DAY_SHIFT;
fat_date|= (month & FAT_DATE_MONTH_MASK) << FAT_DATE_MONTH_SHIFT;
fat_date|= (year & FAT_DATE_YEAR_MASK) << FAT_DATE_YEAR_SHIFT;
return fat_date;
}
#endif
//-----------------------------------------------------------------------------
// fatfs_print_sector:
//-----------------------------------------------------------------------------
#ifdef FATFS_DEBUG
void fatfs_print_sector(uint32 sector, uint8 *data)
{
int i;
int j;
FAT_PRINTF(("Sector %d:\n", sector));
for (i=0;i<FAT_SECTOR_SIZE;i++)
{
if (!((i) % 16))
{
FAT_PRINTF((" %04d: ", i));
}
FAT_PRINTF(("%02x", data[i]));
if (!((i+1) % 4))
{
FAT_PRINTF((" "));
}
if (!((i+1) % 16))
{
FAT_PRINTF((" "));
for (j=0;j<16;j++)
{
char ch = data[i-15+j];
// Is printable?
if (ch > 31 && ch < 127)
{
FAT_PRINTF(("%c", ch));
}
else
{
FAT_PRINTF(("."));
}
}
FAT_PRINTF(("\n"));
}
}
}
#endif

View File

@@ -0,0 +1,63 @@
#ifndef __FAT_MISC_H__
#define __FAT_MISC_H__
#include "fat_defs.h"
#include "fat_opts.h"
//-----------------------------------------------------------------------------
// Defines
//-----------------------------------------------------------------------------
#define MAX_LONGFILENAME_ENTRIES 20
#define MAX_LFN_ENTRY_LENGTH 13
//-----------------------------------------------------------------------------
// Macros
//-----------------------------------------------------------------------------
#define GET_32BIT_WORD(buffer, location) ( ((uint32)buffer[location+3]<<24) + ((uint32)buffer[location+2]<<16) + ((uint32)buffer[location+1]<<8) + (uint32)buffer[location+0] )
#define GET_16BIT_WORD(buffer, location) ( ((uint16)buffer[location+1]<<8) + (uint16)buffer[location+0] )
#define SET_32BIT_WORD(buffer, location, value) { buffer[location+0] = (uint8)((value)&0xFF); \
buffer[location+1] = (uint8)((value>>8)&0xFF); \
buffer[location+2] = (uint8)((value>>16)&0xFF); \
buffer[location+3] = (uint8)((value>>24)&0xFF); }
#define SET_16BIT_WORD(buffer, location, value) { buffer[location+0] = (uint8)((value)&0xFF); \
buffer[location+1] = (uint8)((value>>8)&0xFF); }
//-----------------------------------------------------------------------------
// Structures
//-----------------------------------------------------------------------------
struct lfn_cache
{
#if FATFS_INC_LFN_SUPPORT
// Long File Name Structure (max 260 LFN length)
uint8 String[MAX_LONGFILENAME_ENTRIES][MAX_LFN_ENTRY_LENGTH];
uint8 Null;
#endif
uint8 no_of_strings;
};
//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
void fatfs_lfn_cache_init(struct lfn_cache *lfn, int wipeTable);
void fatfs_lfn_cache_entry(struct lfn_cache *lfn, uint8 *entryBuffer);
char* fatfs_lfn_cache_get(struct lfn_cache *lfn);
int fatfs_entry_lfn_text(struct fat_dir_entry *entry);
int fatfs_entry_lfn_invalid(struct fat_dir_entry *entry);
int fatfs_entry_lfn_exists(struct lfn_cache *lfn, struct fat_dir_entry *entry);
int fatfs_entry_sfn_only(struct fat_dir_entry *entry);
int fatfs_entry_is_dir(struct fat_dir_entry *entry);
int fatfs_entry_is_file(struct fat_dir_entry *entry);
int fatfs_lfn_entries_required(char *filename);
void fatfs_filename_to_lfn(char *filename, uint8 *buffer, int entry, uint8 sfnChk);
void fatfs_sfn_create_entry(char *shortfilename, uint32 size, uint32 startCluster, struct fat_dir_entry *entry, int dir);
int fatfs_lfn_create_sfn(char *sfn_output, char *filename);
int fatfs_lfn_generate_tail(char *sfn_output, char *sfn_input, uint32 tailNum);
void fatfs_convert_from_fat_time(uint16 fat_time, int *hours, int *minutes, int *seconds);
void fatfs_convert_from_fat_date(uint16 fat_date, int *day, int *month, int *year);
uint16 fatfs_convert_to_fat_time(int hours, int minutes, int seconds);
uint16 fatfs_convert_to_fat_date(int day, int month, int year);
void fatfs_print_sector(uint32 sector, uint8 *data);
#endif

View File

@@ -0,0 +1,83 @@
#ifndef __FAT_OPTS_H__
#define __FAT_OPTS_H__
#ifdef FATFS_USE_CUSTOM_OPTS_FILE
#include "fat_custom.h"
#endif
//-------------------------------------------------------------
// Configuration
//-------------------------------------------------------------
// Is the processor little endian (1) or big endian (0)
#ifndef FATFS_IS_LITTLE_ENDIAN
#define FATFS_IS_LITTLE_ENDIAN 1
#endif
// Max filename Length
#ifndef FATFS_MAX_LONG_FILENAME
#define FATFS_MAX_LONG_FILENAME 260
#endif
// Max open files (reduce to lower memory requirements)
#ifndef FATFS_MAX_OPEN_FILES
#define FATFS_MAX_OPEN_FILES 2
#endif
// Number of sectors per FAT_BUFFER (min 1)
#ifndef FAT_BUFFER_SECTORS
#define FAT_BUFFER_SECTORS 1
#endif
// Max FAT sectors to buffer (min 1)
// (mem used is FAT_BUFFERS * FAT_BUFFER_SECTORS * FAT_SECTOR_SIZE)
#ifndef FAT_BUFFERS
#define FAT_BUFFERS 1
#endif
// Size of cluster chain cache (can be undefined)
// Mem used = FAT_CLUSTER_CACHE_ENTRIES * 4 * 2
// Improves access speed considerably
//#define FAT_CLUSTER_CACHE_ENTRIES 128
// Include support for writing files (1 / 0)?
#ifndef FATFS_INC_WRITE_SUPPORT
#define FATFS_INC_WRITE_SUPPORT 1
#endif
// Support long filenames (1 / 0)?
// (if not (0) only 8.3 format is supported)
#ifndef FATFS_INC_LFN_SUPPORT
#define FATFS_INC_LFN_SUPPORT 1
#endif
// Support directory listing (1 / 0)?
#ifndef FATFS_DIR_LIST_SUPPORT
#define FATFS_DIR_LIST_SUPPORT 1
#endif
// Support time/date (1 / 0)?
#ifndef FATFS_INC_TIME_DATE_SUPPORT
#define FATFS_INC_TIME_DATE_SUPPORT 0
#endif
// Include support for formatting disks (1 / 0)?
#ifndef FATFS_INC_FORMAT_SUPPORT
#define FATFS_INC_FORMAT_SUPPORT 0
#endif
// Sector size used
#define FAT_SECTOR_SIZE 512
// Printf output (directory listing / debug)
#ifndef FAT_PRINTF
void ventoy_syslog_printf(const char *Fmt, ...);
#define FAT_PRINTF(a) ventoy_syslog_printf a
#endif
// Time/Date support requires time.h
#if FATFS_INC_TIME_DATE_SUPPORT
#include <time.h>
#endif
#endif

View File

@@ -0,0 +1,514 @@
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// FAT16/32 File IO Library
// V2.6
// Ultra-Embedded.com
// Copyright 2003 - 2012
//
// Email: admin@ultra-embedded.com
//
// License: GPL
// If you would like a version with a more permissive license for use in
// closed source commercial applications please contact me for details.
//-----------------------------------------------------------------------------
//
// This file is part of FAT File IO Library.
//
// FAT File IO Library 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.
//
// FAT File IO 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with FAT File IO Library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#include <string.h>
#include <assert.h>
#include "fat_string.h"
//-----------------------------------------------------------------------------
// fatfs_total_path_levels: Take a filename and path and count the sub levels
// of folders. E.g. C:\folder\file.zip = 1 level
// Acceptable input formats are:
// c:\folder\file.zip
// /dev/etc/samba.conf
// Returns: -1 = Error, 0 or more = Ok
//-----------------------------------------------------------------------------
int fatfs_total_path_levels(char *path)
{
int levels = 0;
char expectedchar;
if (!path)
return -1;
// Acceptable formats:
// c:\folder\file.zip
// /dev/etc/samba.conf
if (*path == '/')
{
expectedchar = '/';
path++;
}
else if (path[1] == ':' || path[2] == '\\')
{
expectedchar = '\\';
path += 3;
}
else
return -1;
// Count levels in path string
while (*path)
{
// Fast forward through actual subdir text to next slash
for (; *path; )
{
// If slash detected escape from for loop
if (*path == expectedchar) { path++; break; }
path++;
}
// Increase number of subdirs founds
levels++;
}
// Subtract the file itself
return levels-1;
}
//-----------------------------------------------------------------------------
// fatfs_get_substring: Get a substring from 'path' which contains the folder
// (or file) at the specified level.
// E.g. C:\folder\file.zip : Level 0 = C:\folder, Level 1 = file.zip
// Returns: -1 = Error, 0 = Ok
//-----------------------------------------------------------------------------
int fatfs_get_substring(char *path, int levelreq, char *output, int max_len)
{
int i;
int pathlen=0;
int levels=0;
int copypnt=0;
char expectedchar;
if (!path || max_len <= 0)
return -1;
// Acceptable formats:
// c:\folder\file.zip
// /dev/etc/samba.conf
if (*path == '/')
{
expectedchar = '/';
path++;
}
else if (path[1] == ':' || path[2] == '\\')
{
expectedchar = '\\';
path += 3;
}
else
return -1;
// Get string length of path
pathlen = (int)strlen (path);
// Loop through the number of times as characters in 'path'
for (i = 0; i<pathlen; i++)
{
// If a '\' is found then increase level
if (*path == expectedchar) levels++;
// If correct level and the character is not a '\' or '/' then copy text to 'output'
if ( (levels == levelreq) && (*path != expectedchar) && (copypnt < (max_len-1)))
output[copypnt++] = *path;
// Increment through path string
path++;
}
// Null Terminate
output[copypnt] = '\0';
// If a string was copied return 0 else return 1
if (output[0] != '\0')
return 0; // OK
else
return -1; // Error
}
//-----------------------------------------------------------------------------
// fatfs_split_path: Full path contains the passed in string.
// Returned is the path string and file Name string
// E.g. C:\folder\file.zip -> path = C:\folder filename = file.zip
// E.g. C:\file.zip -> path = [blank] filename = file.zip
//-----------------------------------------------------------------------------
int fatfs_split_path(char *full_path, char *path, int max_path, char *filename, int max_filename)
{
int strindex;
// Count the levels to the filepath
int levels = fatfs_total_path_levels(full_path);
if (levels == -1)
return -1;
// Get filename part of string
if (fatfs_get_substring(full_path, levels, filename, max_filename) != 0)
return -1;
// If root file
if (levels == 0)
path[0] = '\0';
else
{
strindex = (int)strlen(full_path) - (int)strlen(filename);
if (strindex > max_path)
strindex = max_path;
memcpy(path, full_path, strindex);
path[strindex-1] = '\0';
}
return 0;
}
//-----------------------------------------------------------------------------
// FileString_StrCmpNoCase: Compare two strings case with case sensitivity
//-----------------------------------------------------------------------------
static int FileString_StrCmpNoCase(char *s1, char *s2, int n)
{
int diff;
char a,b;
while (n--)
{
a = *s1;
b = *s2;
// Make lower case if uppercase
if ((a>='A') && (a<='Z'))
a+= 32;
if ((b>='A') && (b<='Z'))
b+= 32;
diff = a - b;
// If different
if (diff)
return diff;
// If run out of strings
if ( (*s1 == 0) || (*s2 == 0) )
break;
s1++;
s2++;
}
return 0;
}
//-----------------------------------------------------------------------------
// FileString_GetExtension: Get index to extension within filename
// Returns -1 if not found or index otherwise
//-----------------------------------------------------------------------------
static int FileString_GetExtension(char *str)
{
int dotPos = -1;
char *strSrc = str;
// Find last '.' in string (if at all)
while (*strSrc)
{
if (*strSrc=='.')
dotPos = (int)(strSrc-str);
strSrc++;
}
return dotPos;
}
//-----------------------------------------------------------------------------
// FileString_TrimLength: Get length of string excluding trailing spaces
// Returns -1 if not found or index otherwise
//-----------------------------------------------------------------------------
static int FileString_TrimLength(char *str, int strLen)
{
int length = strLen;
char *strSrc = str+strLen-1;
// Find last non white space
while (strLen != 0)
{
if (*strSrc == ' ')
length = (int)(strSrc - str);
else
break;
strSrc--;
strLen--;
}
return length;
}
//-----------------------------------------------------------------------------
// fatfs_compare_names: Compare two filenames (without copying or changing origonals)
// Returns 1 if match, 0 if not
//-----------------------------------------------------------------------------
int fatfs_compare_names(char* strA, char* strB)
{
char *ext1 = NULL;
char *ext2 = NULL;
int ext1Pos, ext2Pos;
int file1Len, file2Len;
// Get both files extension
ext1Pos = FileString_GetExtension(strA);
ext2Pos = FileString_GetExtension(strB);
// NOTE: Extension position can be different for matching
// filename if trailing space are present before it!
// Check that if one has an extension, so does the other
if ((ext1Pos==-1) && (ext2Pos!=-1))
return 0;
if ((ext2Pos==-1) && (ext1Pos!=-1))
return 0;
// If they both have extensions, compare them
if (ext1Pos!=-1)
{
// Set pointer to start of extension
ext1 = strA+ext1Pos+1;
ext2 = strB+ext2Pos+1;
// Verify that the file extension lengths match!
if (strlen(ext1) != strlen(ext2))
return 0;
// If they dont match
if (FileString_StrCmpNoCase(ext1, ext2, (int)strlen(ext1))!=0)
return 0;
// Filelength is upto extensions
file1Len = ext1Pos;
file2Len = ext2Pos;
}
// No extensions
else
{
// Filelength is actual filelength
file1Len = (int)strlen(strA);
file2Len = (int)strlen(strB);
}
// Find length without trailing spaces (before ext)
file1Len = FileString_TrimLength(strA, file1Len);
file2Len = FileString_TrimLength(strB, file2Len);
// Check the file lengths match
if (file1Len!=file2Len)
return 0;
// Compare main part of filenames
if (FileString_StrCmpNoCase(strA, strB, file1Len)!=0)
return 0;
else
return 1;
}
//-----------------------------------------------------------------------------
// fatfs_string_ends_with_slash: Does the string end with a slash (\ or /)
//-----------------------------------------------------------------------------
int fatfs_string_ends_with_slash(char *path)
{
if (path)
{
while (*path)
{
// Last character?
if (!(*(path+1)))
{
if (*path == '\\' || *path == '/')
return 1;
}
path++;
}
}
return 0;
}
//-----------------------------------------------------------------------------
// fatfs_get_sfn_display_name: Get display name for SFN entry
//-----------------------------------------------------------------------------
int fatfs_get_sfn_display_name(char* out, char* in)
{
int len = 0;
while (*in && len <= 11)
{
char a = *in++;
if (a == ' ')
continue;
// Make lower case if uppercase
else if ((a>='A') && (a<='Z'))
a+= 32;
*out++ = a;
len++;
}
*out = '\0';
return 1;
}
//-----------------------------------------------------------------------------
// fatfs_get_extension: Get extension of filename passed in 'filename'.
// Returned extension is always lower case.
// Returns: 1 if ok, 0 if not.
//-----------------------------------------------------------------------------
int fatfs_get_extension(char* filename, char* out, int maxlen)
{
int len = 0;
// Get files extension offset
int ext_pos = FileString_GetExtension(filename);
if (ext_pos > 0 && out && maxlen)
{
filename += ext_pos + 1;
while (*filename && len < (maxlen-1))
{
char a = *filename++;
// Make lowercase if uppercase
if ((a>='A') && (a<='Z'))
a+= 32;
*out++ = a;
len++;
}
*out = '\0';
return 1;
}
return 0;
}
//-----------------------------------------------------------------------------
// fatfs_create_path_string: Append path & filename to create file path string.
// Returns: 1 if ok, 0 if not.
//-----------------------------------------------------------------------------
int fatfs_create_path_string(char* path, char *filename, char* out, int maxlen)
{
int len = 0;
char last = 0;
char seperator = '/';
if (path && filename && out && maxlen > 0)
{
while (*path && len < (maxlen-2))
{
last = *path++;
if (last == '\\')
seperator = '\\';
*out++ = last;
len++;
}
// Add a seperator if trailing one not found
if (last != '\\' && last != '/')
*out++ = seperator;
while (*filename && len < (maxlen-1))
{
*out++ = *filename++;
len++;
}
*out = '\0';
return 1;
}
return 0;
}
//-----------------------------------------------------------------------------
// Test Bench
//-----------------------------------------------------------------------------
#ifdef FAT_STRING_TESTBENCH
void main(void)
{
char output[255];
char output2[255];
assert(fatfs_total_path_levels("C:\\folder\\file.zip") == 1);
assert(fatfs_total_path_levels("C:\\file.zip") == 0);
assert(fatfs_total_path_levels("C:\\folder\\folder2\\file.zip") == 2);
assert(fatfs_total_path_levels("C:\\") == -1);
assert(fatfs_total_path_levels("") == -1);
assert(fatfs_total_path_levels("/dev/etc/file.zip") == 2);
assert(fatfs_total_path_levels("/dev/file.zip") == 1);
assert(fatfs_get_substring("C:\\folder\\file.zip", 0, output, sizeof(output)) == 0);
assert(strcmp(output, "folder") == 0);
assert(fatfs_get_substring("C:\\folder\\file.zip", 1, output, sizeof(output)) == 0);
assert(strcmp(output, "file.zip") == 0);
assert(fatfs_get_substring("/dev/etc/file.zip", 0, output, sizeof(output)) == 0);
assert(strcmp(output, "dev") == 0);
assert(fatfs_get_substring("/dev/etc/file.zip", 1, output, sizeof(output)) == 0);
assert(strcmp(output, "etc") == 0);
assert(fatfs_get_substring("/dev/etc/file.zip", 2, output, sizeof(output)) == 0);
assert(strcmp(output, "file.zip") == 0);
assert(fatfs_split_path("C:\\folder\\file.zip", output, sizeof(output), output2, sizeof(output2)) == 0);
assert(strcmp(output, "C:\\folder") == 0);
assert(strcmp(output2, "file.zip") == 0);
assert(fatfs_split_path("C:\\file.zip", output, sizeof(output), output2, sizeof(output2)) == 0);
assert(output[0] == 0);
assert(strcmp(output2, "file.zip") == 0);
assert(fatfs_split_path("/dev/etc/file.zip", output, sizeof(output), output2, sizeof(output2)) == 0);
assert(strcmp(output, "/dev/etc") == 0);
assert(strcmp(output2, "file.zip") == 0);
assert(FileString_GetExtension("C:\\file.zip") == strlen("C:\\file"));
assert(FileString_GetExtension("C:\\file.zip.ext") == strlen("C:\\file.zip"));
assert(FileString_GetExtension("C:\\file.zip.") == strlen("C:\\file.zip"));
assert(FileString_TrimLength("C:\\file.zip", strlen("C:\\file.zip")) == strlen("C:\\file.zip"));
assert(FileString_TrimLength("C:\\file.zip ", strlen("C:\\file.zip ")) == strlen("C:\\file.zip"));
assert(FileString_TrimLength(" ", strlen(" ")) == 0);
assert(fatfs_compare_names("C:\\file.ext", "C:\\file.ext") == 1);
assert(fatfs_compare_names("C:\\file2.ext", "C:\\file.ext") == 0);
assert(fatfs_compare_names("C:\\file .ext", "C:\\file.ext") == 1);
assert(fatfs_compare_names("C:\\file .ext", "C:\\file2.ext") == 0);
assert(fatfs_string_ends_with_slash("C:\\folder") == 0);
assert(fatfs_string_ends_with_slash("C:\\folder\\") == 1);
assert(fatfs_string_ends_with_slash("/path") == 0);
assert(fatfs_string_ends_with_slash("/path/a") == 0);
assert(fatfs_string_ends_with_slash("/path/") == 1);
assert(fatfs_get_extension("/mypath/file.wav", output, 4) == 1);
assert(strcmp(output, "wav") == 0);
assert(fatfs_get_extension("/mypath/file.WAV", output, 4) == 1);
assert(strcmp(output, "wav") == 0);
assert(fatfs_get_extension("/mypath/file.zip", output, 4) == 1);
assert(strcmp(output, "ext") != 0);
assert(fatfs_create_path_string("/mydir1", "myfile.txt", output, sizeof(output)) == 1);
assert(strcmp(output, "/mydir1/myfile.txt") == 0);
assert(fatfs_create_path_string("/mydir2/", "myfile2.txt", output, sizeof(output)) == 1);
assert(strcmp(output, "/mydir2/myfile2.txt") == 0);
assert(fatfs_create_path_string("C:\\mydir3", "myfile3.txt", output, sizeof(output)) == 1);
assert(strcmp(output, "C:\\mydir3\\myfile3.txt") == 0);
}
#endif

View File

@@ -0,0 +1,20 @@
#ifndef __FILESTRING_H__
#define __FILESTRING_H__
//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
int fatfs_total_path_levels(char *path);
int fatfs_get_substring(char *Path, int levelreq, char *output, int max_len);
int fatfs_split_path(char *FullPath, char *Path, int max_path, char *FileName, int max_filename);
int fatfs_compare_names(char* strA, char* strB);
int fatfs_string_ends_with_slash(char *path);
int fatfs_get_sfn_display_name(char* out, char* in);
int fatfs_get_extension(char* filename, char* out, int maxlen);
int fatfs_create_path_string(char* path, char *filename, char* out, int maxlen);
#ifndef NULL
#define NULL 0
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More