30
30
#endif
31
31
#include < stdlib.h>
32
32
#include < string.h>
33
+ #include < limits.h>
33
34
#if DEVICE_STDIO_MESSAGES
34
35
#include < stdio.h>
35
36
#endif
@@ -120,6 +121,17 @@ static void init_serial() {
120
121
#endif
121
122
}
122
123
124
+ /* *
125
+ * Sets errno when file opening fails.
126
+ * Wipes out the filehandle too.
127
+ */
128
+ static int handle_open_errors (int error, unsigned filehandle_idx) {
129
+ errno = -error;
130
+ // Free file handle
131
+ filehandles[filehandle_idx] = NULL ;
132
+ return -1 ;
133
+ }
134
+
123
135
#if MBED_CONF_FILESYSTEM_PRESENT
124
136
static inline int openmode_to_posix (int openmode) {
125
137
int posix = openmode;
@@ -189,7 +201,7 @@ class ManagedDir : public Dir {
189
201
* @return
190
202
* On success, a valid FILEHANDLE is returned.
191
203
* On failure, -1 is returned and errno is set to an appropriate value e.g.
192
- * EBADF a bad file descriptor was found (default errno setting)
204
+ * ENOENT file not found (default errno setting)
193
205
* EMFILE the maximum number of open files was exceeded.
194
206
*
195
207
* */
@@ -219,9 +231,6 @@ extern "C" FILEHANDLE PREFIX(_open)(const char* name, int openmode) {
219
231
}
220
232
#endif
221
233
222
- /* if something goes wrong and errno is not explicly set, errno will be set to EBADF */
223
- errno = EBADF;
224
-
225
234
// find the first empty slot in filehandles
226
235
filehandle_mutex->lock ();
227
236
unsigned int fh_i;
@@ -253,41 +262,30 @@ extern "C" FILEHANDLE PREFIX(_open)(const char* name, int openmode) {
253
262
if (!path.exists ()) {
254
263
/* The first part of the filename (between first 2 '/') is not a
255
264
* registered mount point in the namespace.
256
- * Free file handle.
257
265
*/
258
- filehandles[fh_i] = NULL ;
259
- errno = ENOENT;
260
- return - 1 ;
261
- } else if (path.isFile ()) {
266
+ return handle_open_errors (-ENOENT, fh_i) ;
267
+ }
268
+
269
+ if (path.isFile ()) {
262
270
res = path.file ();
263
271
#if MBED_CONF_FILESYSTEM_PRESENT
264
272
} else {
265
273
FileSystem *fs = path.fileSystem ();
266
274
if (fs == NULL ) {
267
- /* The filesystem instance managing the namespace under the mount point
268
- * has not been found. Free file handle */
269
- errno = ENOENT;
270
- filehandles[fh_i] = NULL ;
271
- return -1 ;
275
+ return handle_open_errors (-ENOENT, fh_i);
272
276
}
273
277
int posix_mode = openmode_to_posix (openmode);
274
278
File *file = new ManagedFile;
275
279
int err = file->open (fs, path.fileName (), posix_mode);
276
280
if (err < 0 ) {
277
- errno = -err;
278
281
delete file;
279
- } else {
280
- res = file;
282
+ return handle_open_errors (err, fh_i);
281
283
}
284
+ res = file;
282
285
#endif
283
286
}
284
287
}
285
288
286
- if (res == NULL ) {
287
- // Free file handle
288
- filehandles[fh_i] = NULL ;
289
- return -1 ;
290
- }
291
289
filehandles[fh_i] = res;
292
290
293
291
return fh_i + 3 ; // +3 as filehandles 0-2 are stdin/out/err
@@ -296,10 +294,12 @@ extern "C" FILEHANDLE PREFIX(_open)(const char* name, int openmode) {
296
294
extern " C" int PREFIX (_close)(FILEHANDLE fh) {
297
295
if (fh < 3 ) return 0 ;
298
296
299
- errno = EBADF;
300
297
FileHandle* fhc = filehandles[fh-3 ];
301
298
filehandles[fh-3 ] = NULL ;
302
- if (fhc == NULL ) return -1 ;
299
+ if (fhc == NULL ) {
300
+ errno = EBADF;
301
+ return -1 ;
302
+ }
303
303
304
304
int err = fhc->close ();
305
305
if (err < 0 ) {
@@ -317,7 +317,6 @@ extern "C" int PREFIX(_write)(FILEHANDLE fh, const unsigned char *buffer, unsign
317
317
#endif
318
318
int n; // n is the number of bytes written
319
319
320
- errno = EBADF;
321
320
if (fh < 3 ) {
322
321
#if DEVICE_SERIAL
323
322
if (!stdio_uart_inited) init_serial ();
@@ -338,7 +337,10 @@ extern "C" int PREFIX(_write)(FILEHANDLE fh, const unsigned char *buffer, unsign
338
337
n = length;
339
338
} else {
340
339
FileHandle* fhc = filehandles[fh-3 ];
341
- if (fhc == NULL ) return -1 ;
340
+ if (fhc == NULL ) {
341
+ errno = EBADF;
342
+ return -1 ;
343
+ }
342
344
343
345
n = fhc->write (buffer, length);
344
346
if (n < 0 ) {
@@ -359,7 +361,6 @@ extern "C" int PREFIX(_read)(FILEHANDLE fh, unsigned char *buffer, unsigned int
359
361
#endif
360
362
int n; // n is the number of bytes read
361
363
362
- errno = EBADF;
363
364
if (fh < 3 ) {
364
365
// only read a character at a time from stdin
365
366
#if DEVICE_SERIAL
@@ -390,7 +391,10 @@ extern "C" int PREFIX(_read)(FILEHANDLE fh, unsigned char *buffer, unsigned int
390
391
n = 1 ;
391
392
} else {
392
393
FileHandle* fhc = filehandles[fh-3 ];
393
- if (fhc == NULL ) return -1 ;
394
+ if (fhc == NULL ) {
395
+ errno = EBADF;
396
+ return -1 ;
397
+ }
394
398
395
399
n = fhc->read (buffer, length);
396
400
if (n < 0 ) {
@@ -410,51 +414,69 @@ extern "C" int PREFIX(_istty)(FILEHANDLE fh)
410
414
extern " C" int _isatty (FILEHANDLE fh)
411
415
#endif
412
416
{
413
- errno = EBADF;
414
417
/* stdin, stdout and stderr should be tty */
415
418
if (fh < 3 ) return 1 ;
416
419
417
420
FileHandle* fhc = filehandles[fh-3 ];
418
- if (fhc == NULL ) return -1 ;
421
+ if (fhc == NULL ) {
422
+ errno = EBADF;
423
+ return 0 ;
424
+ }
419
425
420
- int err = fhc->isatty ();
421
- if (err < 0 ) {
422
- errno = -err;
423
- return -1 ;
424
- } else {
426
+ int tty = fhc->isatty ();
427
+ if (tty < 0 ) {
428
+ errno = -tty;
425
429
return 0 ;
430
+ } else {
431
+ return tty;
426
432
}
427
433
}
428
434
429
435
extern " C"
430
436
#if defined(__ARMCC_VERSION)
431
- int _sys_seek (FILEHANDLE fh, long position )
437
+ int _sys_seek (FILEHANDLE fh, long offset )
432
438
#elif defined(__ICCARM__)
433
439
long __lseek (int fh, long offset, int whence)
434
440
#else
435
441
int _lseek (FILEHANDLE fh, int offset, int whence)
436
442
#endif
437
443
{
438
- errno = EBADF;
439
- if (fh < 3 ) return 0 ;
444
+ #if defined(__ARMCC_VERSION)
445
+ int whence = SEEK_SET;
446
+ #endif
447
+ if (fh < 3 ) {
448
+ errno = ESPIPE;
449
+ return -1 ;
450
+ }
440
451
441
452
FileHandle* fhc = filehandles[fh-3 ];
442
- if (fhc == NULL ) return -1 ;
453
+ if (fhc == NULL ) {
454
+ errno = EBADF;
455
+ return -1 ;
456
+ }
443
457
444
- #if defined(__ARMCC_VERSION)
445
- return fhc->seek (position, SEEK_SET);
446
- #else
447
- return fhc->seek (offset, whence);
448
- #endif
458
+ off_t off = fhc->seek (offset, whence);
459
+ if (off < 0 ) {
460
+ errno = -off;
461
+ return -1 ;
462
+ }
463
+ // Assuming INT_MAX = LONG_MAX, so we don't care about prototype difference
464
+ if (off > INT_MAX) {
465
+ errno = EOVERFLOW;
466
+ return -1 ;
467
+ }
468
+ return off;
449
469
}
450
470
451
471
#ifdef __ARMCC_VERSION
452
472
extern " C" int PREFIX (_ensure)(FILEHANDLE fh) {
453
- errno = EBADF;
454
473
if (fh < 3 ) return 0 ;
455
474
456
475
FileHandle* fhc = filehandles[fh-3 ];
457
- if (fhc == NULL ) return -1 ;
476
+ if (fhc == NULL ) {
477
+ errno = EBADF;
478
+ return -1 ;
479
+ }
458
480
459
481
int err = fhc->sync ();
460
482
if (err < 0 ) {
@@ -466,13 +488,27 @@ extern "C" int PREFIX(_ensure)(FILEHANDLE fh) {
466
488
}
467
489
468
490
extern " C" long PREFIX (_flen)(FILEHANDLE fh) {
469
- errno = EBADF;
470
- if (fh < 3 ) return 0 ;
491
+ if (fh < 3 ) {
492
+ errno = EINVAL;
493
+ return -1 ;
494
+ }
471
495
472
496
FileHandle* fhc = filehandles[fh-3 ];
473
- if (fhc == NULL ) return -1 ;
497
+ if (fhc == NULL ) {
498
+ errno = EBADF;
499
+ return -1 ;
500
+ }
474
501
475
- return fhc->size ();
502
+ off_t size = fhc->size ();
503
+ if (size < 0 ) {
504
+ errno = -size;
505
+ return -1 ;
506
+ }
507
+ if (size > LONG_MAX) {
508
+ errno = EOVERFLOW;
509
+ return -1 ;
510
+ }
511
+ return size;
476
512
}
477
513
#endif
478
514
@@ -491,10 +527,12 @@ extern "C" int _fstat(int fd, struct stat *st) {
491
527
namespace std {
492
528
extern " C" int remove (const char *path) {
493
529
#if MBED_CONF_FILESYSTEM_PRESENT
494
- errno = EBADF;
495
530
FilePath fp (path);
496
531
FileSystem *fs = fp.fileSystem ();
497
- if (fs == NULL ) return -1 ;
532
+ if (fs == NULL ) {
533
+ errno = ENOENT;
534
+ return -1 ;
535
+ }
498
536
499
537
int err = fs->remove (fp.fileName ());
500
538
if (err < 0 ) {
@@ -511,14 +549,21 @@ extern "C" int remove(const char *path) {
511
549
512
550
extern " C" int rename (const char *oldname, const char *newname) {
513
551
#if MBED_CONF_FILESYSTEM_PRESENT
514
- errno = EBADF;
515
552
FilePath fpOld (oldname);
516
553
FilePath fpNew (newname);
517
554
FileSystem *fsOld = fpOld.fileSystem ();
518
555
FileSystem *fsNew = fpNew.fileSystem ();
519
556
557
+ if (fsOld == NULL ) {
558
+ errno = ENOENT;
559
+ return -1 ;
560
+ }
561
+
520
562
/* rename only if both files are on the same FS */
521
- if (fsOld != fsNew || fsOld == NULL ) return -1 ;
563
+ if (fsOld != fsNew) {
564
+ errno = EXDEV;
565
+ return -1 ;
566
+ }
522
567
523
568
int err = fsOld->rename (fpOld.fileName (), fpNew.fileName ());
524
569
if (err < 0 ) {
@@ -552,11 +597,12 @@ extern "C" char *_sys_command_string(char *cmd, int len) {
552
597
553
598
extern " C" DIR *opendir (const char *path) {
554
599
#if MBED_CONF_FILESYSTEM_PRESENT
555
- errno = EBADF;
556
-
557
600
FilePath fp (path);
558
601
FileSystem* fs = fp.fileSystem ();
559
- if (fs == NULL ) return NULL ;
602
+ if (fs == NULL ) {
603
+ errno = ENOENT;
604
+ return NULL ;
605
+ }
560
606
561
607
Dir *dir = new ManagedDir;
562
608
int err = dir->open (fs, fp.fileName ());
@@ -903,7 +949,25 @@ void mbed_set_unbuffered_stream(FILE *_file) {
903
949
#endif
904
950
}
905
951
906
- int mbed_getc (FILE *_file){
952
+ /* Applications are expected to use fdopen()
953
+ * not this function directly. This code had to live here because FILE and FileHandle
954
+ * processes are all linked together here.
955
+ */
956
+ std::FILE *mbed_fdopen (FileHandle *fh, const char *mode)
957
+ {
958
+ char buf[12 ]; /* :0x12345678 + null byte */
959
+ std::sprintf (buf, " :%p" , fh);
960
+ std::FILE *stream = std::fopen (buf, mode);
961
+ /* newlib-nano doesn't appear to ever call _isatty itself, so
962
+ * happily fully buffers an interactive stream. Deal with that here.
963
+ */
964
+ if (stream && fh->isatty ()) {
965
+ mbed_set_unbuffered_stream (stream);
966
+ }
967
+ return stream;
968
+ }
969
+
970
+ int mbed_getc (std::FILE *_file){
907
971
#if defined (__ICCARM__)
908
972
/* This is only valid for unbuffered streams*/
909
973
int res = std::fgetc (_file);
0 commit comments