From e272f773b558f9d9a8d37533c40ae45247fbf396 Mon Sep 17 00:00:00 2001 From: Terje Io Date: Tue, 11 Nov 2025 16:51:08 +0100 Subject: [PATCH] Refactored the tool table HAL API a bit to improve functionality. Added tool name, pocket number and some lathe specific data fields to the $# tool output when available from the tool table. If name is available it will be output as a push message on M6 if there is no message in the same block. Added support for directory up, .., to VFS. Added new option to $650 - File systems options to enable hierarchical listing of files and directories via $F and $F+ commands. --- changelog.md | 26 ++++++++++++++++++++++++++ config.h | 49 ++++++++++++++++++++++++++++++++++++++++++++++--- core_handlers.h | 6 ++---- gcode.c | 42 ++++++++++++++++++++++++------------------ gcode.h | 8 ++++++++ grbl.h | 2 +- grbllib.c | 2 +- ngc_params.c | 6 +++--- report.c | 11 ++++++++++- settings.c | 45 +++++++++++++++++++++++++++------------------ settings.h | 7 ++++--- stream.c | 3 ++- vfs.c | 21 +++++++++++++++++++-- 13 files changed, 173 insertions(+), 55 deletions(-) diff --git a/changelog.md b/changelog.md index 8ccbeea..d84f563 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,31 @@ ## grblHAL changelog +Build 20251111 + +Core: + +* Refactored the tool table HAL API a bit to improve functionality. +Added tool name, pocket number and some lathe specific data fields to the `$#` tool output when available from the tool table. +If name is available it will be output as a push message on `M6` if there is no message in the same block. + +* Added support for directory up, `..`, to VFS. + +* Added new option to `$650` - _File systems options_ to enable hierarchical listing of files and directories via `$F` and `$F+` commands. +When enabled directories are added to the output with file size set to `-1` and only the contents of the current directory is reported. +The `$F=` command can then be used to set the current working direcory \(CWD\). `$F=..` can be used to move up one level and `$F=/` to move to the root directory. +Files or directory names for `$F`, `$F+` `$F<` and `$FD` commands not starting with `/` will executed be relative to the CWD. + +Plugins: + +* Misc, tooltable: removed limit on max number of tools, it is now constrained by available RAM. Added name \(remark, comment\) to imported data and +a new command, `$TTLOAD`, that can be used to reload the tool table after it has been updated. + +* EEPROM: added experimental code that allows mounting unused part of large EEPROM as littlefs file system. This may then be used to store a file based tooltable etc. + +* SD Card, littlefs VFS wrapper: added support for `vfs_chdir()` \(change directory\) to allow ftp access to subdirectories. + +--- + Build 20251109 Core: diff --git a/config.h b/config.h index 0026e53..825447b 100644 --- a/config.h +++ b/config.h @@ -542,7 +542,7 @@ Set to \ref On or 1 to enable experimental support for expressions. Some LinuxCNC extensions are supported, conditionals and subroutines are not. */ #if !defined NGC_EXPRESSIONS_ENABLE || defined __DOXYGEN__ -#define NGC_EXPRESSIONS_ENABLE Off +#define NGC_EXPRESSIONS_ENABLE On #endif /*! \def NGC_PARAMETERS_ENABLE @@ -1467,11 +1467,14 @@ and less range over the total 255 PWM levels to signal different spindle speeds. // Homing settings (Group_Homing) /*! @name $22 - Setting_HomingEnable -\brief Enable homing. +\brief Enable and control homing functionality. Requires homing cycles to be defined by \ref DEFAULT_HOMING_CYCLE_0 - \ref DEFAULT_HOMING_CYCLE_2 +. -\internal Bit 0 in settings.homing.flags. */ ///@{ +/*! /def DEFAULT_HOMING_ENABLE +\brief Enables homing overall. +\internal Bit 0 in settings.homing.flags. +*/ #if !defined DEFAULT_HOMING_ENABLE || defined __DOXYGEN__ #define DEFAULT_HOMING_ENABLE Off // Default disabled. Set to \ref On or 1 to enable. #endif @@ -2119,6 +2122,46 @@ Default stream format settings for ModBus RTU stream. #endif ///@} +/*! @name $681 - Setting_ModBus_StreamFormat +Default stream format settings for ModBus RTU stream. +*/ +///@{ +#if !defined DEFAULT_MODBUS_STREAM_PARITY || defined __DOXYGEN__ +#define DEFAULT_MODBUS_STREAM_PARITY 0 // 0 = None, 1 = Even, 2 = Odd +#endif +///@} + +/*! @name $650 - Setting_FSOptions +Filing systems options. +*/ +///@{ +/*! /def DEFAULT_FS_SD_AUTOMOUNT +\brief Auto mount SD card on startup. +\internal Bit 0 in settings.fs_options.mask. +*/ +#if !defined DEFAULT_FS_SD_AUTOMOUNT || defined __DOXYGEN__ +#define DEFAULT_FS_SD_AUTOMOUNT Off // Default disabled. Set to \ref On or 1 to enable. +#endif + +/*! /def DEFAULT_FS_LITLLEFS_HIDDEN +\brief Hides LittleFS mount from directory listings. +\internal Bit 1 in settings.fs_options.mask. +*/ +#if !defined DEFAULT_FS_LITLLEFS_HIDDEN || defined __DOXYGEN__ +#define DEFAULT_FS_LITLLEFS_HIDDEN Off // Default disabled. Set to \ref On or 1 to enable. +#endif + +/*! /def DEFAULT_FS_HIERACHICAL_LISTING +\brief +Adds directory entries in $F and $F+ output to allow hierarchical navigation of the directoy tree. +\internal Bit 2 in settings.fs_options.mask. +*/ +#if !defined DEFAULT_FS_HIERACHICAL_LISTING || defined __DOXYGEN__ +#define DEFAULT_FS_HIERACHICAL_LISTING Off // Default disabled. Set to \ref On or 1 to enable. +#endif +///@} + + // Axis settings (Group_XAxis - Group_VAxis) /*! @name $10x - Setting_AxisStepsPerMM diff --git a/core_handlers.h b/core_handlers.h index f52696f..d923918 100644 --- a/core_handlers.h +++ b/core_handlers.h @@ -136,10 +136,9 @@ typedef status_code_t (*on_macro_execute_ptr)(macro_id_t macro); // macro implem typedef void (*on_macro_return_ptr)(void); typedef void (*on_file_demarcate_ptr)(bool start); -typedef tool_data_t *(*get_tool_ptr)(tool_id_t tool_id); -typedef tool_data_t *(*get_tool_by_idx_ptr)(uint32_t idx); +typedef tool_table_entry_t *(*get_tool_ptr)(tool_id_t tool_id); +typedef tool_table_entry_t *(*get_tool_by_idx_ptr)(uint32_t idx); typedef bool (*set_tool_data_ptr)(tool_data_t *tool_data); -typedef pocket_id_t (*get_pocket_ptr)(tool_id_t tool_id); typedef bool (*clear_tool_data_ptr)(void); typedef struct { @@ -147,7 +146,6 @@ typedef struct { get_tool_ptr get_tool; get_tool_by_idx_ptr get_tool_by_idx; set_tool_data_ptr set_tool; - get_pocket_ptr get_pocket; clear_tool_data_ptr clear; } tool_table_t; diff --git a/gcode.c b/gcode.c index 59e09a8..89090bb 100644 --- a/gcode.c +++ b/gcode.c @@ -373,16 +373,16 @@ void gc_init (bool stop) { #if COMPATIBILITY_LEVEL > 1 memset(&gc_state, 0, sizeof(parser_state_t)); - gc_state.tool = grbl.tool_table.get_tool(0); + gc_state.tool = grbl.tool_table.get_tool(0)->data; if(grbl.tool_table.n_tools == 0) memset(gc_state.tool, 0, sizeof(tool_data_t)); #else if(sys.cold_start) { memset(&gc_state, 0, sizeof(parser_state_t)); if(settings.flags.tool_persistent) - gc_state.tool = grbl.tool_table.get_tool(settings.tool_id); + gc_state.tool = grbl.tool_table.get_tool(settings.tool_id)->data; if(gc_state.tool == NULL) - gc_state.tool = grbl.tool_table.get_tool(0); + gc_state.tool = grbl.tool_table.get_tool(0)->data; if(grbl.tool_table.n_tools == 0) { memset(gc_state.tool, 0, sizeof(tool_data_t)); if(settings.flags.tool_persistent) @@ -503,12 +503,21 @@ static void add_offset (const coord_data_t *offset) system_flag_wco_change(); } -static tool_data_t *tool_get_pending (tool_id_t tool_id) +static tool_data_t *tool_get_pending (tool_id_t tool_id, char **message) { static tool_data_t tool_data = {0}; - if(grbl.tool_table.n_tools) - return grbl.tool_table.get_tool(tool_id); + if(grbl.tool_table.n_tools) { + + tool_table_entry_t *tool = grbl.tool_table.get_tool(tool_id); + + if(message && tool->name) { + if((*message = malloc(strlen(tool->name) + 1))) + strcpy(*message, tool->name); + } + + return tool->data; + } memcpy(&tool_data, gc_state.tool, sizeof(tool_data_t)); tool_data.tool_id = tool_id; @@ -1711,7 +1720,7 @@ status_code_t gc_execute_block (char *block) case 'T': if(mantissa > 0) FAIL(Status_GcodeCommandValueNotInteger); - if(grbl.tool_table.n_tools ? (grbl.tool_table.get_tool((tool_id_t)int_value) == NULL) : (int_value > MAX_TOOL_NUMBER)) + if(grbl.tool_table.n_tools ? (grbl.tool_table.get_tool((tool_id_t)int_value)->data == NULL) : (int_value > MAX_TOOL_NUMBER)) FAIL(Status_GcodeIllegalToolTableEntry); word_bit.parameter.t = On; gc_block.values.t = isnan(value) ? 0xFFFFFFFF : int_value; @@ -2059,7 +2068,7 @@ status_code_t gc_execute_block (char *block) FAIL(Status_GcodeValueWordMissing); if(!isintf(gc_block.values.q)) FAIL(Status_GcodeCommandValueNotInteger); - if(grbl.tool_table.n_tools ? grbl.tool_table.get_tool((tool_id_t)gc_block.values.q) == NULL : gc_block.values.q > MAX_TOOL_NUMBER) + if(grbl.tool_table.n_tools ? grbl.tool_table.get_tool((tool_id_t)gc_block.values.q)->data == NULL : gc_block.values.q > MAX_TOOL_NUMBER) FAIL(Status_GcodeIllegalToolTableEntry); gc_block.values.t = (uint32_t)gc_block.values.q; @@ -2402,7 +2411,7 @@ status_code_t gc_execute_block (char *block) if(gc_block.words.h) { if(gc_block.values.h == 0 && !settings.macro_atc_flags.random_toolchanger) gc_block.values.h = gc_block.values.t; // !! no tool clear offset - if(!grbl.tool_table.get_tool((tool_id_t)gc_block.values.h)) + if(!grbl.tool_table.get_tool((tool_id_t)gc_block.values.h)->data) FAIL(Status_GcodeIllegalToolTableEntry); gc_block.words.h = Off; } else @@ -2414,7 +2423,7 @@ status_code_t gc_execute_block (char *block) case ToolLengthOffset_ApplyAdditional: if(grbl.tool_table.n_tools) { if(gc_block.words.h) { - if(gc_block.values.h == 0 || !grbl.tool_table.get_tool((tool_id_t)gc_block.values.h)) + if(gc_block.values.h == 0 || !grbl.tool_table.get_tool((tool_id_t)gc_block.values.h)->data) FAIL(Status_GcodeIllegalToolTableEntry); gc_block.words.h = Off; } else @@ -2532,8 +2541,8 @@ status_code_t gc_execute_block (char *block) tool_data_t *tool_data; - if((tool_data = grbl.tool_table.get_tool((tool_id_t)p_value)) == NULL) - FAIL(Status_GcodeIllegalToolTableEntry); // [Greater than max allowed tool number] + if((tool_data = grbl.tool_table.get_tool((tool_id_t)p_value)->data) == NULL) + FAIL(Status_GcodeIllegalToolTableEntry); // [Greater than max allowed tool number or not in tool table] if(gc_block.words.r) { tool_data->radius = gc_block.values.r; @@ -2546,9 +2555,6 @@ status_code_t gc_execute_block (char *block) FAIL(Status_SettingReadFail); #endif - if(gc_block.values.l == 1) - tool_data = grbl.tool_table.get_tool((tool_id_t)p_value); - idx = N_AXIS; do { if(bit_istrue(axis_words.mask, bit(--idx))) { @@ -3427,7 +3433,7 @@ status_code_t gc_execute_block (char *block) if(!check_mode) { - tool_data_t *pending_tool = tool_get_pending(gc_state.tool_pending); + tool_data_t *pending_tool = tool_get_pending(gc_state.tool_pending, NULL); // If M6 not available or M61 commanded set new tool immediately if(set_tool || (hal.driver_cap.atc ? !hal.tool.change : settings.tool_change.mode == ToolChange_Ignore || !(hal.stream.suspend_read || hal.tool.change))) { @@ -3494,7 +3500,7 @@ status_code_t gc_execute_block (char *block) // [6. Change tool ]: Delegated to (possible) driver implementation if(command_words.M6 && !set_tool && !check_mode) { - tool_data_t *pending_tool = tool_get_pending(gc_state.tool_pending); + tool_data_t *pending_tool = tool_get_pending(gc_state.tool_pending, plan_data.message ? NULL : &plan_data.message); protocol_buffer_synchronize(); @@ -3760,7 +3766,7 @@ status_code_t gc_execute_block (char *block) gc_state.modal.tool_offset_mode = gc_block.modal.tool_offset_mode; if(gc_state.modal.tool_offset_mode == ToolLengthOffset_Enable || gc_state.modal.tool_offset_mode == ToolLengthOffset_ApplyAdditional) - tool_data = grbl.tool_table.get_tool((tool_id_t)gc_block.values.h); + tool_data = grbl.tool_table.get_tool((tool_id_t)gc_block.values.h)->data; do { diff --git a/gcode.h b/gcode.h index b4fb136..e256648 100644 --- a/gcode.h +++ b/gcode.h @@ -589,9 +589,17 @@ typedef struct { tool_id_t tool_id; //!< Tool number } tool_data_t; +//! Tool table entry. +typedef struct { + const char *name; + tool_data_t *data; + pocket_id_t pocket; +} tool_table_entry_t; + typedef struct { tool_data_t tool; pocket_id_t pocket_id; + char name[101]; } tool_pocket_t; /*! \brief Parser state diff --git a/grbl.h b/grbl.h index 08798ad..448beb7 100644 --- a/grbl.h +++ b/grbl.h @@ -42,7 +42,7 @@ #else #define GRBL_VERSION "1.1f" #endif -#define GRBL_BUILD 20251109 +#define GRBL_BUILD 20251111 #define GRBL_URL "https://github.com/grblHAL" diff --git a/grbllib.c b/grbllib.c index 76cfb1f..3488cdb 100644 --- a/grbllib.c +++ b/grbllib.c @@ -432,7 +432,7 @@ int grbl_enter (void) task_add_delayed(auto_realtime_report, NULL, settings.report_interval); if(hal.driver_cap.sd_card || hal.driver_cap.littlefs) { - fs_options_t fs_options = {0}; + fs_options_t fs_options = { .hierarchical_listing = On }; fs_options.lfs_hidden = hal.driver_cap.littlefs; fs_options.sd_mount_on_boot = hal.driver_cap.sd_card; setting_remove_elements(Setting_FSOptions, fs_options.mask); diff --git a/ngc_params.c b/ngc_params.c index 9a9d7d8..5d2ef58 100644 --- a/ngc_params.c +++ b/ngc_params.c @@ -596,7 +596,7 @@ float ngc_named_param_get_by_id (ncg_name_param_id_t id) break; case NGCParam_current_pocket: - value = (float)grbl.tool_table.get_pocket(gc_state.tool->tool_id); + value = (float)grbl.tool_table.get_tool(gc_state.tool->tool_id)->pocket; break; case NGCParam_selected_tool: @@ -604,7 +604,7 @@ float ngc_named_param_get_by_id (ncg_name_param_id_t id) break; case NGCParam_selected_pocket: - value = gc_state.tool_pending != gc_state.tool->tool_id ? (float)grbl.tool_table.get_pocket(gc_state.tool_pending) : -1.0f; + value = gc_state.tool_pending != gc_state.tool->tool_id ? (float)grbl.tool_table.get_tool(gc_state.tool_pending)->pocket : -1.0f; break; case NGCParam_call_level: @@ -1094,7 +1094,7 @@ static status_code_t macro_get_tool_offset (void) status = Status_GcodeValueWordMissing; else if(grbl.tool_table.n_tools && ngc_param_get(17 /* Q word */, &tool_id) && ngc_param_get(18 /* R word */, &axis_id)) { - tool_data_t *tool_data = grbl.tool_table.get_tool((tool_id_t)tool_id); + tool_data_t *tool_data = grbl.tool_table.get_tool((tool_id_t)tool_id)->data; if(tool_data && (uint8_t)axis_id < N_AXIS) { ngc_named_param_set("_value", tool_data->offset.values[(uint8_t)axis_id]); diff --git a/report.c b/report.c index 1bb3b77..256aeba 100644 --- a/report.c +++ b/report.c @@ -646,9 +646,10 @@ void report_ngc_parameters (void) hal.stream.write("]" ASCII_EOL); tool_data_t *tool_data; + tool_table_entry_t *tool; for (idx = 1; idx <= grbl.tool_table.n_tools; idx++) { - if((tool_data = grbl.tool_table.get_tool_by_idx((uint32_t)idx)) && + if((tool_data = (tool = grbl.tool_table.get_tool_by_idx((uint32_t)idx))->data) && (settings.macro_atc_flags.random_toolchanger ? tool_data->tool_id >= 0 : tool_data->tool_id > 0)) { hal.stream.write("[T:"); hal.stream.write(uitoa(tool_data->tool_id)); @@ -656,7 +657,15 @@ void report_ngc_parameters (void) hal.stream.write(get_axis_values(tool_data->offset.values)); hal.stream.write("|"); hal.stream.write(get_axis_value(tool_data->radius)); + hal.stream.write("|6,0,0|"); + hal.stream.write(tool->name ? tool->name : ""); // TODO: sanitize name? (| not allowed) + if(tool->pocket >= 0) { + hal.stream.write("|"); + hal.stream.write(uitoa((uint32_t)tool->pocket)); + } hal.stream.write("]" ASCII_EOL); + if(tool->name) + hal.delay_ms(5, NULL); } } diff --git a/settings.c b/settings.c index 8d03567..ccb8373 100644 --- a/settings.c +++ b/settings.c @@ -358,6 +358,10 @@ PROGMEM const settings_t defaults = { .safety_door.spindle_on_delay = DEFAULT_SAFETY_DOOR_SPINDLE_DELAY, .safety_door.coolant_on_delay = DEFAULT_SAFETY_DOOR_COOLANT_DELAY, + .fs_options.sd_mount_on_boot = DEFAULT_FS_SD_AUTOMOUNT, + .fs_options.lfs_hidden = DEFAULT_FS_LITLLEFS_HIDDEN, + .fs_options.hierarchical_listing = DEFAULT_FS_HIERACHICAL_LISTING, + .modbus_baud = DEFAULT_MODBUS_STREAM_BAUD, .modbus_stream_format.value = (DEFAULT_MODBUS_STREAM_PARITY << 4), @@ -455,7 +459,7 @@ static char ganged_axes[] = "X-Axis,Y-Axis,Z-Axis"; static on_file_demarcate_ptr on_file_demarcate; static char step_us_min[4]; -static char fs_options[] = "Auto mount SD card,Hide LittleFS"; +static char fs_options[] = "Auto mount SD card,Hide LittleFS,Hierarchical listing"; static char spindle_types[100] = ""; static char axis_dist[4] = "mm"; static char axis_rate[8] = "mm/min"; @@ -2510,18 +2514,22 @@ static bool settings_set_tool_data (tool_data_t *tool) } // Read selected tool data from persistent storage. -static tool_data_t *settings_get_tool_data (tool_id_t tool_id) +static tool_table_entry_t *settings_get_tool_data (tool_id_t tool_id) { - tool_data_t *tool = tool_id <= N_TOOLS ? &tool_data[tool_id] : NULL; + static tool_table_entry_t tool = {0}; - if(tool_id && tool && !(hal.nvs.type != NVS_None && - hal.nvs.memcpy_from_nvs((uint8_t *)tool, NVS_ADDR_TOOL_TABLE + (tool_id - 1) * (sizeof(tool_data_t) + NVS_CRC_BYTES), - sizeof(tool_data_t), true) == NVS_TransferResult_OK && tool->tool_id == tool_id)) { - memset(tool, 0, sizeof(tool_data_t)); - tool->tool_id = tool_id; + tool.data = tool_id <= N_TOOLS ? &tool_data[tool_id] : NULL; + + if(tool_id && tool.data && !(hal.nvs.type != NVS_None && + hal.nvs.memcpy_from_nvs((uint8_t *)tool.data, NVS_ADDR_TOOL_TABLE + (tool_id - 1) * (sizeof(tool_data_t) + NVS_CRC_BYTES), + sizeof(tool_data_t), true) == NVS_TransferResult_OK && tool.data->tool_id == tool_id)) { + memset(tool.data, 0, sizeof(tool_data_t)); + tool.data->tool_id = tool_id; } - return tool; + tool.pocket = (pocket_id_t)(tool.data ? tool_id : -1); + + return &tool; } // Clear all tool data in persistent storage. @@ -2550,13 +2558,20 @@ static bool settings_set_tool_data (tool_data_t *tool_data) } // Read selected tool data from persistent storage. -static tool_data_t *settings_get_tool_data (tool_id_t tool_id) +static tool_table_entry_t *settings_get_tool_data (tool_id_t tool_id) { + static tool_table_entry_t tool = {0}; - if(tool_id <= MAX_TOOL_NUMBER) + if(tool_id <= MAX_TOOL_NUMBER) { tool_data.tool_id = tool_id; + tool.pocket = (pocket_id_t)tool_id; + tool.data = &tool_data; + } else { + tool.data = NULL; + tool.pocket = (pocket_id_t)-1; + } - return tool_id <= MAX_TOOL_NUMBER ? &tool_data : NULL; + return &tool; } // Clear all tool data in persistent storage. @@ -2569,11 +2584,6 @@ static bool settings_clear_tool_data (void) #endif // N_TOOLS -static pocket_id_t settings_get_tool_pocket (tool_id_t tool_id) -{ - return (pocket_id_t)tool_id; -} - // Sanity check of settings, board map could have been changed... static void sanity_check (void) { @@ -3412,7 +3422,6 @@ void settings_init (void) grbl.tool_table.get_tool = settings_get_tool_data; grbl.tool_table.get_tool_by_idx = (get_tool_by_idx_ptr)settings_get_tool_data; grbl.tool_table.set_tool = settings_set_tool_data; - grbl.tool_table.get_pocket = settings_get_tool_pocket; grbl.tool_table.clear = settings_clear_tool_data; } diff --git a/settings.h b/settings.h index dd3114b..cfe2a85 100644 --- a/settings.h +++ b/settings.h @@ -773,9 +773,10 @@ typedef union { uint8_t value; uint8_t mask; struct { - uint8_t sd_mount_on_boot :1, - lfs_hidden :1, - unused :6; + uint8_t sd_mount_on_boot :1, + lfs_hidden :1, + hierarchical_listing :1, + unused :5; }; } fs_options_t; diff --git a/stream.c b/stream.c index 4fc0c6d..91fb394 100644 --- a/stream.c +++ b/stream.c @@ -515,6 +515,8 @@ bool stream_close (io_stream_t const *stream) void stream_set_defaults (const io_stream_t *stream, uint32_t baud_rate) { + stream->set_enqueue_rt_handler(protocol_enqueue_realtime_command); + if(stream->set_baud_rate) stream->set_baud_rate(baud_rate); @@ -528,7 +530,6 @@ void stream_set_defaults (const io_stream_t *stream, uint32_t baud_rate) stream->reset_write_buffer(); stream->reset_read_buffer(); - stream->set_enqueue_rt_handler(protocol_enqueue_realtime_command); } // MPG stream diff --git a/vfs.c b/vfs.c index 2caf24a..f3f4349 100644 --- a/vfs.c +++ b/vfs.c @@ -27,6 +27,10 @@ #include "hal.h" #include "vfs.h" +#ifndef VFS_CWD_LENGTH +#define VFS_CWD_LENGTH 100 +#endif + #ifdef ARDUINO_SAM_DUE #undef feof #endif @@ -202,7 +206,7 @@ static vfs_mount_t root = { .next = NULL }; static vfs_mount_t *cwdmount = &root; -static char cwd[100] = "/"; +static char cwd[VFS_CWD_LENGTH] = "/"; volatile int vfs_errno = 0; vfs_events_t vfs = {0}; @@ -381,9 +385,13 @@ int vfs_rmdir (const char *path) int vfs_chdir (const char *path) { int ret; + char *p; vfs_errno = 0; + if(!strcmp("..", path) && strcmp("/", (path = cwd)) && (p = strrchr(cwd, '/'))) + *(p + (p == cwd ? 1 : 0)) = '\0'; + if(*path != '/' && strcmp(cwd, "/")) { if(strcmp(path, "..")) { if(strlen(cwd) > 1) @@ -511,11 +519,20 @@ int vfs_chmod (const char *filename, vfs_st_mode_t attr, vfs_st_mode_t mask) int vfs_stat (const char *filename, vfs_stat_t *st) { + char tmp[VFS_CWD_LENGTH], *p; + + if(!strcmp("..", filename)) { + strcpy(tmp, cwd); + if((p = strrchr(tmp, '/'))) + *(p + (p == tmp ? 1 : 0)) = '\0'; + filename = tmp; + } + vfs_mount_t *mount = get_mount(filename); int ret = mount ? mount->vfs->fstat(get_filename(mount, filename), st) : -1; - if(ret == -1 && strchr(filename, '/') == NULL && !strcmp("/", cwd)) { + if(ret == -1 && (!strcmp("/", filename) || (strchr(filename, '/') == NULL && !strcmp("/", cwd)))) { strcat(cwd, filename); mount = get_mount(cwd);