13
13
// limitations under the License.
14
14
15
15
#include " vfs_api.h"
16
+ #include < errno.h>
17
+ #include < stdlib.h>
18
+ #include < string.h>
16
19
17
20
using namespace fs ;
18
21
@@ -38,8 +41,47 @@ FileImplPtr VFSImpl::open(const char *fpath, const char *mode, const bool create
38
41
strcpy (temp, _mountpoint);
39
42
strcat (temp, fpath);
40
43
44
+ // Try to open as file first - let the file operation handle errors
45
+ if (mode && mode[0 ] != ' r' ) {
46
+ // For write modes, attempt to create directories if needed
47
+ if (create) {
48
+ char *token;
49
+ char *folder = (char *)malloc (strlen (fpath) + 1 );
50
+
51
+ int start_index = 0 ;
52
+ int end_index = 0 ;
53
+
54
+ token = strchr (fpath + 1 , ' /' );
55
+ end_index = (token - fpath);
56
+
57
+ while (token != NULL ) {
58
+ memcpy (folder, fpath + start_index, end_index - start_index);
59
+ folder[end_index - start_index] = ' \0 ' ;
60
+
61
+ if (!VFSImpl::mkdir (folder)) {
62
+ log_e (" Creating folder: %s failed!" , folder);
63
+ free (folder);
64
+ free (temp);
65
+ return FileImplPtr ();
66
+ }
67
+
68
+ token = strchr (token + 1 , ' /' );
69
+ if (token != NULL ) {
70
+ end_index = (token - fpath);
71
+ memset (folder, 0 , strlen (folder));
72
+ }
73
+ }
74
+
75
+ free (folder);
76
+ }
77
+
78
+ // Try to open the file directly - let fopen handle errors
79
+ free (temp);
80
+ return std::make_shared<VFSFileImpl>(this , fpath, mode);
81
+ }
82
+
83
+ // For read mode, try to open as file first
41
84
struct stat st;
42
- // file found
43
85
if (!stat (temp, &st)) {
44
86
free (temp);
45
87
if (S_ISREG (st.st_mode ) || S_ISDIR (st.st_mode )) {
@@ -49,54 +91,15 @@ FileImplPtr VFSImpl::open(const char *fpath, const char *mode, const bool create
49
91
return FileImplPtr ();
50
92
}
51
93
52
- // try to open this as directory (might be mount point)
94
+ // Try to open as directory (might be mount point)
53
95
DIR *d = opendir (temp);
54
96
if (d) {
55
97
closedir (d);
56
98
free (temp);
57
99
return std::make_shared<VFSFileImpl>(this , fpath, mode);
58
100
}
59
101
60
- // file not found but mode permits file creation without folder creation
61
- if ((mode && mode[0 ] != ' r' ) && (!create)) {
62
- free (temp);
63
- return std::make_shared<VFSFileImpl>(this , fpath, mode);
64
- }
65
-
66
- // //file not found but mode permits file creation and folder creation
67
- if ((mode && mode[0 ] != ' r' ) && create) {
68
-
69
- char *token;
70
- char *folder = (char *)malloc (strlen (fpath) + 1 );
71
-
72
- int start_index = 0 ;
73
- int end_index = 0 ;
74
-
75
- token = strchr (fpath + 1 , ' /' );
76
- end_index = (token - fpath);
77
-
78
- while (token != NULL ) {
79
- memcpy (folder, fpath + start_index, end_index - start_index);
80
- folder[end_index - start_index] = ' \0 ' ;
81
-
82
- if (!VFSImpl::mkdir (folder)) {
83
- log_e (" Creating folder: %s failed!" , folder);
84
- return FileImplPtr ();
85
- }
86
-
87
- token = strchr (token + 1 , ' /' );
88
- if (token != NULL ) {
89
- end_index = (token - fpath);
90
- memset (folder, 0 , strlen (folder));
91
- }
92
- }
93
-
94
- free (folder);
95
- free (temp);
96
- return std::make_shared<VFSFileImpl>(this , fpath, mode);
97
- }
98
-
99
- log_e (" %s does not exist, no permits for creation" , temp);
102
+ // File not found and read mode - return empty
100
103
free (temp);
101
104
return FileImplPtr ();
102
105
}
@@ -125,10 +128,7 @@ bool VFSImpl::rename(const char *pathFrom, const char *pathTo) {
125
128
log_e (" bad arguments" );
126
129
return false ;
127
130
}
128
- if (!exists (pathFrom)) {
129
- log_e (" %s does not exists" , pathFrom);
130
- return false ;
131
- }
131
+
132
132
size_t mountpointLen = strlen (_mountpoint);
133
133
char *temp1 = (char *)malloc (strlen (pathFrom) + mountpointLen + 1 );
134
134
if (!temp1) {
@@ -148,6 +148,7 @@ bool VFSImpl::rename(const char *pathFrom, const char *pathTo) {
148
148
strcpy (temp2, _mountpoint);
149
149
strcat (temp2, pathTo);
150
150
151
+ // Let rename() handle the error if source doesn't exist
151
152
auto rc = ::rename (temp1, temp2);
152
153
free (temp1);
153
154
free (temp2);
@@ -165,16 +166,6 @@ bool VFSImpl::remove(const char *fpath) {
165
166
return false ;
166
167
}
167
168
168
- VFSFileImpl f (this , fpath, " r" );
169
- if (!f || f.isDirectory ()) {
170
- if (f) {
171
- f.close ();
172
- }
173
- log_e (" %s does not exists or is directory" , fpath);
174
- return false ;
175
- }
176
- f.close ();
177
-
178
169
char *temp = (char *)malloc (strlen (fpath) + strlen (_mountpoint) + 1 );
179
170
if (!temp) {
180
171
log_e (" malloc failed" );
@@ -184,6 +175,7 @@ bool VFSImpl::remove(const char *fpath) {
184
175
strcpy (temp, _mountpoint);
185
176
strcat (temp, fpath);
186
177
178
+ // Let unlink() handle the error if file doesn't exist
187
179
auto rc = unlink (temp);
188
180
free (temp);
189
181
return rc == 0 ;
@@ -195,17 +187,6 @@ bool VFSImpl::mkdir(const char *fpath) {
195
187
return false ;
196
188
}
197
189
198
- VFSFileImpl f (this , fpath, " r" );
199
- if (f && f.isDirectory ()) {
200
- f.close ();
201
- // log_w("%s already exists", fpath);
202
- return true ;
203
- } else if (f) {
204
- f.close ();
205
- log_e (" %s is a file" , fpath);
206
- return false ;
207
- }
208
-
209
190
char *temp = (char *)malloc (strlen (fpath) + strlen (_mountpoint) + 1 );
210
191
if (!temp) {
211
192
log_e (" malloc failed" );
@@ -215,9 +196,15 @@ bool VFSImpl::mkdir(const char *fpath) {
215
196
strcpy (temp, _mountpoint);
216
197
strcat (temp, fpath);
217
198
199
+ // Let mkdir() handle the error if directory already exists
218
200
auto rc = ::mkdir (temp, ACCESSPERMS);
219
201
free (temp);
220
- return rc == 0 ;
202
+
203
+ // EEXIST means directory already exists, which is fine
204
+ if (rc == 0 || errno == EEXIST) {
205
+ return true ;
206
+ }
207
+ return false ;
221
208
}
222
209
223
210
bool VFSImpl::rmdir (const char *fpath) {
@@ -231,16 +218,6 @@ bool VFSImpl::rmdir(const char *fpath) {
231
218
return false ;
232
219
}
233
220
234
- VFSFileImpl f (this , fpath, " r" );
235
- if (!f || !f.isDirectory ()) {
236
- if (f) {
237
- f.close ();
238
- }
239
- log_e (" %s does not exists or is a file" , fpath);
240
- return false ;
241
- }
242
- f.close ();
243
-
244
221
char *temp = (char *)malloc (strlen (fpath) + strlen (_mountpoint) + 1 );
245
222
if (!temp) {
246
223
log_e (" malloc failed" );
@@ -250,6 +227,7 @@ bool VFSImpl::rmdir(const char *fpath) {
250
227
strcpy (temp, _mountpoint);
251
228
strcat (temp, fpath);
252
229
230
+ // Let rmdir() handle the error if directory doesn't exist
253
231
auto rc = ::rmdir (temp);
254
232
free (temp);
255
233
return rc == 0 ;
@@ -271,8 +249,27 @@ VFSFileImpl::VFSFileImpl(VFSImpl *fs, const char *fpath, const char *mode) : _fs
271
249
return ;
272
250
}
273
251
252
+ // Try to open as file first
253
+ _f = fopen (temp, mode);
254
+ if (_f) {
255
+ _isDirectory = false ;
256
+ if (_stat.st_blksize == 0 ) {
257
+ setvbuf (_f, NULL , _IOFBF, DEFAULT_FILE_BUFFER_SIZE);
258
+ }
259
+ free (temp);
260
+ return ;
261
+ }
262
+
263
+ // Try to open as directory
264
+ _d = opendir (temp);
265
+ if (_d) {
266
+ _isDirectory = true ;
267
+ free (temp);
268
+ return ;
269
+ }
270
+
271
+ // If neither worked, try to stat to determine type
274
272
if (!stat (temp, &_stat)) {
275
- // file found
276
273
if (S_ISREG (_stat.st_mode )) {
277
274
_isDirectory = false ;
278
275
_f = fopen (temp, mode);
@@ -292,18 +289,8 @@ VFSFileImpl::VFSFileImpl(VFSImpl *fs, const char *fpath, const char *mode) : _fs
292
289
log_e (" Unknown type 0x%08X for file %s" , ((_stat.st_mode ) & _IFMT), temp);
293
290
}
294
291
} else {
295
- // file not found
296
- if (!mode || mode[0 ] == ' r' ) {
297
- // try to open as directory
298
- _d = opendir (temp);
299
- if (_d) {
300
- _isDirectory = true ;
301
- } else {
302
- _isDirectory = false ;
303
- // log_w("stat(%s) failed", temp);
304
- }
305
- } else {
306
- // lets create this new file
292
+ // File not found - this is normal for write modes
293
+ if (mode && mode[0 ] != ' r' ) {
307
294
_isDirectory = false ;
308
295
_f = fopen (temp, mode);
309
296
if (!_f) {
0 commit comments