/ firmware / src / console / path.cpp
path.cpp
 1  #include "path.h"
 2  
 3  #include <string.h>
 4  #include <stdio.h>
 5  
 6  //------------------------------------------
 7  //  Path utilities — port of Rust path.rs
 8  //------------------------------------------
 9  
10  const char *console::path::home_dir() {
11    return "/";
12  }
13  
14  const char *console::path::display_cwd(const char *cwd) {
15    static char display[128];
16    const char *home = home_dir();
17    size_t home_len = strlen(home);
18  
19    if (strcmp(cwd, home) == 0) {
20      return "~";
21    }
22  
23    if (home_len > 1 && strncmp(cwd, home, home_len) == 0) {
24      snprintf(display, sizeof(display), "~%s", cwd + home_len);
25      return display;
26    }
27  
28    return cwd;
29  }
30  
31  void console::path::apply_cd(char *cwd, size_t cap, const char *arg) {
32    if (!arg || arg[0] == '\0' || strcmp(arg, "~") == 0) {
33      strlcpy(cwd, home_dir(), cap);
34      return;
35    }
36  
37    if (strcmp(arg, "/") == 0) {
38      strlcpy(cwd, "/", cap);
39      return;
40    }
41  
42    // Absolute path — start fresh
43    char work[128];
44    if (arg[0] == '/') {
45      strlcpy(work, "/", sizeof(work));
46      arg++;
47    } else if (arg[0] == '~' && (arg[1] == '/' || arg[1] == '\0')) {
48      strlcpy(work, home_dir(), sizeof(work));
49      arg += (arg[1] == '/') ? 2 : 1;
50    } else {
51      strlcpy(work, cwd, sizeof(work));
52    }
53  
54    // Walk each path component
55    char component[64];
56    while (*arg) {
57      const char *slash = strchr(arg, '/');
58      size_t len = slash ? (size_t)(slash - arg) : strlen(arg);
59  
60      if (len == 0 || (len == 1 && arg[0] == '.')) {
61        // empty or "." — skip
62      } else if (len == 2 && arg[0] == '.' && arg[1] == '.') {
63        // ".." — go up
64        char *last_slash = strrchr(work, '/');
65        if (last_slash && last_slash != work) {
66          *last_slash = '\0';
67        } else {
68          strlcpy(work, "/", sizeof(work));
69        }
70      } else {
71        // regular name — append
72        if (len >= sizeof(component)) len = sizeof(component) - 1;
73        memcpy(component, arg, len);
74        component[len] = '\0';
75  
76        if (strcmp(work, "/") != 0)
77          strlcat(work, "/", sizeof(work));
78        strlcat(work, component, sizeof(work));
79      }
80  
81      if (!slash) break;
82      arg = slash + 1;
83    }
84  
85    strlcpy(cwd, work, cap);
86  }