|
44 | 44 | #include <libgen.h> |
45 | 45 | #include <errno.h> |
46 | 46 | #include <debug.h> |
47 | | -#include <time.h> |
48 | 47 | #include "nsh.h" |
49 | 48 |
|
50 | | -#define CONFIG_LIBC_LOCALTIME 1 |
51 | | -#define CONFIG_CLOCK_TIMEKEEPING 1 |
52 | | - |
| 49 | +#ifdef CONFIG_ARCH_SIM |
| 50 | +# include <time.h> |
| 51 | +#endif |
53 | 52 |
|
54 | 53 | #if !defined(CONFIG_DISABLE_MOUNTPOINT) |
55 | 54 | # include <sys/mount.h> |
@@ -364,52 +363,132 @@ static int ls_handler(FAR struct nsh_vtbl_s *vtbl, FAR const char *dirpath, |
364 | 363 |
|
365 | 364 | if ((lsflags & (LSFLAGS_SIZE | LSFLAGS_LONG | LSFLAGS_UID_GID)) != 0) |
366 | 365 | { |
367 | | - struct stat buf; |
| 366 | + struct stat buf; |
368 | 367 |
|
369 | | - memset(&buf, 0, sizeof(buf)); |
| 368 | + memset(&buf, 0, sizeof(struct stat)); |
370 | 369 |
|
371 | | - /* stat the file */ |
372 | | - if (entryp != NULL) |
373 | | - { |
374 | | - FAR char *fullpath = nsh_getdirpath(vtbl, dirpath, entryp->d_name); |
375 | | - ret = stat(fullpath, &buf); |
376 | | - free(fullpath); |
377 | | - } |
378 | | - else |
379 | | - { |
380 | | - ret = stat(dirpath, &buf); |
381 | | - } |
| 370 | + /* If entryp is provided, listing a directory and need to |
| 371 | + * construct the full path to stat the file. Otherwise, dirpath |
| 372 | + * is the target itself. (no separate file name as entryp) |
| 373 | + */ |
382 | 374 |
|
383 | | - #ifdef CONFIG_CLOCK_TIMEKEEPING |
384 | | - if (ret == 0 && buf.st_mtime > 0 && buf.st_mtime < 0x7FFFFFFF) |
385 | | - { |
386 | | - struct tm tm; |
387 | | - time_t t = buf.st_mtime; |
| 375 | + if (entryp != NULL) |
| 376 | + { |
| 377 | + FAR char *fullpath = nsh_getdirpath(vtbl, dirpath, entryp->d_name); |
| 378 | + ret = stat(fullpath, &buf); |
| 379 | + free(fullpath); |
| 380 | + } |
| 381 | + else |
| 382 | + { |
| 383 | + ret = stat(dirpath, &buf); |
| 384 | + } |
388 | 385 |
|
389 | | - #ifdef CONFIG_LIBC_LOCALTIME |
390 | | - localtime_r(&t, &tm); |
391 | | - nsh_output(vtbl, " %04d-%02d-%02d %02d:%02d", |
392 | | - tm.tm_year + 1900, |
393 | | - tm.tm_mon + 1, |
394 | | - tm.tm_mday, |
395 | | - tm.tm_hour, |
396 | | - tm.tm_min); |
397 | | - #else |
398 | | - nsh_output(vtbl, " %ld", (long)t); |
399 | | - #endif |
400 | | - } |
401 | | - else |
402 | | - { |
403 | | - nsh_output(vtbl, " ----/--/-- --:--"); |
404 | | - } |
405 | | - #endif |
| 386 | +#ifdef CONFIG_CLOCK_TIMEKEEPING |
| 387 | + /* manual epoch time to date calculation to reduce extra memory |
| 388 | + * by using includes For boards with minimal flash. |
| 389 | + */ |
| 390 | + |
| 391 | +# ifdef CONFIG_ARCH_SIM |
| 392 | + struct timespec ts; |
| 393 | + |
| 394 | + /* This pulls the ACTUAL current time from your Linux Host */ |
| 395 | + |
| 396 | + /* Sometime defaults to 2008 */ |
| 397 | + |
| 398 | + if (clock_gettime(CLOCK_REALTIME, &ts) == 0) |
| 399 | + { |
| 400 | + clock_settime(CLOCK_REALTIME, &ts); |
| 401 | + } |
| 402 | +# endif |
| 403 | + |
| 404 | + /* for referencing /data : if not mounted the reference will fail. */ |
| 405 | + |
| 406 | +# if defined(CONFIG_ARCH_SIM) && defined(CONFIG_FS_HOSTFS) |
| 407 | + static bool g_time_synced = false; |
| 408 | + |
| 409 | + if (!g_time_synced) |
| 410 | + { |
| 411 | + struct stat hstat; |
| 412 | + |
| 413 | + /* Data section always maintains the current time value. */ |
| 414 | + |
| 415 | + if (stat("/data", &hstat) == 0) |
| 416 | + { |
| 417 | + struct timespec ts_sync; |
| 418 | + |
| 419 | + ts_sync.tv_sec = hstat.st_mtime; |
| 420 | + ts_sync.tv_nsec = 0; |
406 | 421 |
|
| 422 | + /* This is the magic line that sets the system clock */ |
407 | 423 |
|
408 | | - memset(&buf, 0, sizeof(struct stat)); |
| 424 | + if (clock_settime(CLOCK_REALTIME, &ts_sync) == 0) |
| 425 | + { |
| 426 | + g_time_synced = true; |
| 427 | + } |
| 428 | + } |
| 429 | + } |
| 430 | +# endif |
| 431 | + |
| 432 | + if (ret == 0 && buf.st_mtime > 0 && buf.st_mtime < 0x7fffffff) |
| 433 | + { |
| 434 | + uint32_t seconds = (uint32_t)buf.st_mtime; |
| 435 | + uint32_t minutes = seconds / 60; |
| 436 | + uint32_t hours = minutes / 60; |
| 437 | + uint32_t days = hours / 24; |
| 438 | + uint32_t y = 1970; |
| 439 | + uint32_t m = 0; |
| 440 | + |
| 441 | + while (1) |
| 442 | + { |
| 443 | + uint32_t diy = (y % 4 == 0 && (y % 100 != 0 || |
| 444 | + y % 400 == 0)) ? 366 : 365; |
| 445 | + |
| 446 | + if (days < diy) |
| 447 | + { |
| 448 | + break; |
| 449 | + } |
| 450 | + |
| 451 | + days -= diy; |
| 452 | + y++; |
| 453 | + } |
| 454 | + |
| 455 | + static const uint8_t dim[] = |
| 456 | + { |
| 457 | + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 |
| 458 | + }; |
| 459 | + |
| 460 | + for (m = 0; m < 12; m++) |
| 461 | + { |
| 462 | + uint32_t d_m = dim[m]; |
| 463 | + |
| 464 | + if (m == 1 && (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))) |
| 465 | + { |
| 466 | + d_m = 29; |
| 467 | + } |
| 468 | + |
| 469 | + if (days < d_m) |
| 470 | + { |
| 471 | + break; |
| 472 | + } |
| 473 | + |
| 474 | + days -= d_m; |
| 475 | + } |
| 476 | + |
| 477 | + nsh_output(vtbl, " %04u-%02u-%02u %02u:%02u:%02u", |
| 478 | + (unsigned int)y, (unsigned int)m + 1, |
| 479 | + (unsigned int)days + 1, (unsigned int)(hours % 24), |
| 480 | + (unsigned int)(minutes % 60), |
| 481 | + (unsigned int)(seconds % 60)); |
| 482 | + } |
| 483 | + else |
| 484 | + { |
| 485 | + /* Incase valid time entry was not maintained in the stat struct. */ |
409 | 486 |
|
410 | | - /* stat the file */ |
| 487 | + nsh_output(vtbl, " ----/--/-- --:--"); |
| 488 | + } |
| 489 | +#endif |
411 | 490 |
|
412 | | - if (entryp != NULL) |
| 491 | + if (entryp != NULL) |
413 | 492 | { |
414 | 493 | FAR char *fullpath = nsh_getdirpath(vtbl, dirpath, entryp->d_name); |
415 | 494 | ret = stat(fullpath, &buf); |
@@ -561,39 +640,24 @@ static int ls_handler(FAR struct nsh_vtbl_s *vtbl, FAR const char *dirpath, |
561 | 640 |
|
562 | 641 | if ((lsflags & LSFLAGS_SIZE) != 0) |
563 | 642 | { |
| 643 | +#ifdef CONFIG_HAVE_FLOAT |
564 | 644 | if (lsflags & LSFLAGS_HUMANREADBLE && buf.st_size >= KB) |
565 | 645 | { |
566 | | - uint32_t integer_part; |
567 | | - uint32_t decimal_part; |
568 | | - uint32_t unit; |
569 | | - char suffix; |
570 | | - |
571 | | - /* Determine the appropriate unit and suffix */ |
572 | | - |
573 | 646 | if (buf.st_size >= GB) |
574 | 647 | { |
575 | | - unit = GB; |
576 | | - suffix = 'G'; |
| 648 | + nsh_output(vtbl, "%11.1fG", (float)buf.st_size / GB); |
577 | 649 | } |
578 | 650 | else if (buf.st_size >= MB) |
579 | 651 | { |
580 | | - unit = MB; |
581 | | - suffix = 'M'; |
| 652 | + nsh_output(vtbl, "%11.1fM", (float)buf.st_size / MB); |
582 | 653 | } |
583 | 654 | else |
584 | 655 | { |
585 | | - unit = KB; |
586 | | - suffix = 'K'; |
| 656 | + nsh_output(vtbl, "%11.1fK", (float)buf.st_size / KB); |
587 | 657 | } |
588 | | - |
589 | | - /* Use integer arithmetic to avoid floating point */ |
590 | | - |
591 | | - integer_part = buf.st_size / unit; |
592 | | - decimal_part = ((buf.st_size % unit) * 10) / unit; |
593 | | - nsh_output(vtbl, "%10" PRIu32 ".%" PRIu32 "%c", |
594 | | - integer_part, decimal_part, suffix); |
595 | 658 | } |
596 | 659 | else |
| 660 | +#endif |
597 | 661 | { |
598 | 662 | nsh_output(vtbl, "%12" PRIdOFF, buf.st_size); |
599 | 663 | } |
|
0 commit comments