-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathffwrappers.cpp
More file actions
169 lines (154 loc) · 5.44 KB
/
Copy pathffwrappers.cpp
File metadata and controls
169 lines (154 loc) · 5.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "ffwrappers.h"
#include "FrensHelpers.h"
// This file contains some wrapper functions for the FatFs library:
// - my_chdir for f_chdir: Change and keep track of the current working directory.
// - my_getcwd for f_getcwd: Get the current tracked working directory.
// These wrappers are written because when using exfat filesystem, f_getcwd always returns the root directory.
// See http://elm-chan.org/fsw/ff/doc/getcwd.html
// Using fat32, f_getcwd works as expected.
// The wrappers are used to track the current directory and normalize paths.
#define MAX_SEGMENTS 10 // Maximum number of segments in a path
// Normalize a path by resolving "..", ".", and duplicate slashes
// This function normalizes a given path by removing unnecessary components
// Example: "/home/../user//docs/./file.txt" becomes "/user/docs/file.txt"
// This function uses a stack to keep track of the components of the path
int normalize_path(const char *input, char *output, size_t output_size)
{
const char *segments[MAX_SEGMENTS];
int lengths[MAX_SEGMENTS];
int top = 0;
const char *p = input;
while (*p == '/')
p++; // Skip leading slashes
while (*p)
{
const char *start = p;
// Move to the end of this segment
while (*p && *p != '/')
p++;
int len = p - start;
if (len == 0 || (len == 1 && start[0] == '.'))
{
// skip
}
else if (len == 2 && start[0] == '.' && start[1] == '.')
{
if (top > 0)
top--;
}
else
{
if (top >= MAX_SEGMENTS)
{
// Too many segments — prevent buffer overflow
return -1;
}
segments[top] = start;
lengths[top] = len;
top++;
}
while (*p == '/')
p++; // Skip duplicate slashes
}
// Build the output path
char *out = output;
size_t remaining = output_size;
if (top == 0)
{
if (remaining < 2)
return -1; // Need space for '/' and '\0'
*out++ = '/';
*out = '\0';
return 0;
}
for (int i = 0; i < top; i++)
{
//printf("Remaining: %d\n", remaining);
if (remaining < 2)
return -1; // Need at least '/' + '\0'
*out++ = '/';
remaining--;
//printf("Length[i]=%d, remaining=%d\n", lengths[i], remaining);
if ((size_t)lengths[i] >= remaining)
return -1; // Not enough space
memcpy(out, segments[i], lengths[i]);
out += lengths[i];
remaining -= lengths[i];
}
*out = '\0';
return 0;
}
static TCHAR current_dir[FF_MAX_LFN] = "/"; // Static variable to store the current directory
#define BUFFERSIZE (FF_MAX_LFN * sizeof(TCHAR))
// Wrapper function for f_chdir that tracks the current directory
FRESULT my_chdir(const TCHAR *path)
{
#if 0
TCHAR *temp = (TCHAR *)Frens::f_malloc(BUFFERSIZE);
TCHAR *normalized = (TCHAR *)Frens::f_malloc(BUFFERSIZE);
FRESULT fr;
// Check if path is absolute
if (path[0] == '/')
{
strncpy(temp, path, BUFFERSIZE - 1);
temp[BUFFERSIZE- 1] = '\0'; // Ensure null termination
}
else
{
// If the path is relative, append it to the current directory
snprintf(temp, BUFFERSIZE, "%s/%s", current_dir, path);
}
// Normalize the resulting path (resolve "..", ".", and duplicate slashes)
if (normalize_path(temp, normalized, BUFFERSIZE) == 0)
{
// Normalization successful, proceed with changing directory
// Call the actual f_chdir function
if ((fr = f_chdir(normalized)) == FR_OK)
{
// Update the static variable if f_chdir succeeds
strncpy(current_dir, normalized, BUFFERSIZE - 1);
current_dir[BUFFERSIZE- 1] = '\0'; // Ensure null termination
}
printf("Changed directory to: %s\n", current_dir);
}
else
{
printf("Error normalizing path: %s\n", temp);
fr = FR_INVALID_PARAMETER; // Return error if normalization fails
}
Frens::f_free(normalized);
Frens::f_free(temp);
return fr;
#else
return f_chdir(path); // Call the actual f_chdir function
#endif
}
// Function to retrieve the current directory
//
// my_getcwd is a wrapper for f_getcwd that returns the current tracked directory.
// This is necessary because on some filesystems (e.g., exFAT), f_getcwd always returns the root directory.
// The function uses a static variable (current_dir) to keep track of the current directory as changed by my_chdir.
// It copies the tracked directory to the provided buffer, ensuring null termination and checking for buffer size.
// Returns FR_OK on success, or FR_INVALID_PARAMETER if the buffer is too small.
FRESULT my_getcwd(TCHAR *buffer, UINT len)
{
#if 0
// char tempdir[FF_MAX_LFN];
if (len < strlen(current_dir) + 1)
{
return FR_INVALID_PARAMETER; // Buffer too small
}
strncpy(buffer, current_dir, len);
buffer[len - 1] = '\0'; // Ensure null termination
// printf("Current tracked directory : %s\n", buffer);
// f_getcwd(tempdir, sizeof(tempdir));
// printf("Directory reported by f_getcwd: %s\n", tempdir);
return FR_OK;
#else
return f_getcwd(buffer, len); // Call the actual f_getcwd function
// Note: This may not work as expected with exFAT, as it always returns the root directory.
#endif
}