Subversion Repositories svn.mios32

Rev

Rev 2471 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2471 Rev 2617
Line 1... Line 1...
1
// $Id: file.c 2471 2017-01-10 21:16:45Z tk $
1
// $Id: file.c 2617 2018-12-20 00:02:42Z tk $
2
//! \defgroup FILE
2
//! \defgroup FILE
3
//!
3
//!
4
//! File access layer for FatFS
4
//! File access layer for FatFS
5
//!
5
//!
6
//! Frontend functions to read/write files.\n
6
//! Frontend functions to read/write files.\n
Line 38... Line 38...
38
#include <mios32.h>
38
#include <mios32.h>
39
39
40
#include <ff.h>
40
#include <ff.h>
41
#include <diskio.h>
41
#include <diskio.h>
42
#include <string.h>
42
#include <string.h>
-
 
43
#include <ctype.h>
43
44
44
#include "file.h"
45
#include "file.h"
45
46
46
#ifndef MIOS32_FAMILY_EMULATION
47
#ifndef MIOS32_FAMILY_EMULATION
47
# include <FreeRTOS.h>
48
# include <FreeRTOS.h>
Line 71... Line 72...
71
// can be used as additional debugging help if FILE_*ERR returned by function
72
// can be used as additional debugging help if FILE_*ERR returned by function
72
u32 file_dfs_errno;
73
u32 file_dfs_errno;
73
74
74
// for percentage display during copy operations
75
// for percentage display during copy operations
75
u8 file_copy_percentage;
76
u8 file_copy_percentage;
-
 
77
-
 
78
-
 
79
/////////////////////////////////////////////////////////////////////////////
-
 
80
// Local types
-
 
81
/////////////////////////////////////////////////////////////////////////////
-
 
82
-
 
83
// from https://www.gnu.org/software/tar/manual/html_node/Standard.html
-
 
84
typedef struct
-
 
85
{                              /* byte offset */
-
 
86
  char name[100];               /*   0 */
-
 
87
  char mode[8];                 /* 100 */
-
 
88
  char uid[8];                  /* 108 */
-
 
89
  char gid[8];                  /* 116 */
-
 
90
  char size[12];                /* 124 */
-
 
91
  char mtime[12];               /* 136 */
-
 
92
  char chksum[8];               /* 148 */
-
 
93
  char typeflag;                /* 156 */
-
 
94
  char linkname[100];           /* 157 */
-
 
95
  char magic[6];                /* 257 */
-
 
96
  char version[2];              /* 263 */
-
 
97
  char uname[32];               /* 265 */
-
 
98
  char gname[32];               /* 297 */
-
 
99
  char devmajor[8];             /* 329 */
-
 
100
  char devminor[8];             /* 337 */
-
 
101
  char prefix[155];             /* 345 */
-
 
102
  char fill_to_512[12];         /* 500 */
-
 
103
                                /* 512 */
-
 
104
} tar_posix_header;
76
105
77
106
78
/////////////////////////////////////////////////////////////////////////////
107
/////////////////////////////////////////////////////////////////////////////
79
// Local prototypes
108
// Local prototypes
80
/////////////////////////////////////////////////////////////////////////////
109
/////////////////////////////////////////////////////////////////////////////
81
110
82
static s32 FILE_MountFS(void);
111
static s32 FILE_MountFS(void);
-
 
112
-
 
113
static s32 FILE_CreateTarRecursive(char *filename, char *src_path, u8 exclude_tar_files, u8 depth, u8 max_depth, u32 *num_dirs, u32 *num_files);
-
 
114
static s32 FILE_CreateTarHeader(char *filename, char *src_path, u8 is_dir, u32 filesize);
83
115
84
116
85
/////////////////////////////////////////////////////////////////////////////
117
/////////////////////////////////////////////////////////////////////////////
86
// Local variables
118
// Local variables
87
/////////////////////////////////////////////////////////////////////////////
119
/////////////////////////////////////////////////////////////////////////////
Line 820... Line 852...
820
#if DEBUG_VERBOSE_LEVEL >= 2
852
#if DEBUG_VERBOSE_LEVEL >= 2
821
    DEBUG_MSG("[FILE_Copy] Failed to read sector at position 0x%08x, status: %u\n", file_read.fptr, file_dfs_errno);
853
    DEBUG_MSG("[FILE_Copy] Failed to read sector at position 0x%08x, status: %u\n", file_read.fptr, file_dfs_errno);
822
#endif
854
#endif
823
    successcount = 0;
855
    successcount = 0;
824
    status = FILE_ERR_READ;
856
    status = FILE_ERR_READ;
825
      } else if( successcount && f_write(&file_write, tmp_buffer, successcount, &successcount_wr) != FR_OK ) {
857
      } else if( successcount && (file_dfs_errno=f_write(&file_write, tmp_buffer, successcount, &successcount_wr)) != FR_OK ) {
826
#if DEBUG_VERBOSE_LEVEL >= 2
858
#if DEBUG_VERBOSE_LEVEL >= 2
827
    DEBUG_MSG("[FILE_Copy] Failed to write sector at position 0x%08x, status: %u\n", file_write.fptr, file_dfs_errno);
859
    DEBUG_MSG("[FILE_Copy] Failed to write sector at position 0x%08x, status: %u\n", file_write.fptr, file_dfs_errno);
828
#endif
860
#endif
829
    status = FILE_ERR_WRITE;
861
    status = FILE_ERR_WRITE;
830
      } else {
862
      } else {
Line 1423... Line 1455...
1423
  }
1455
  }
1424
1456
1425
  return num_bytes;
1457
  return num_bytes;
1426
}
1458
}
1427
1459
-
 
1460
-
 
1461
/////////////////////////////////////////////////////////////////////////////
-
 
1462
// Creates a tar file (recursively)
-
 
1463
/////////////////////////////////////////////////////////////////////////////
-
 
1464
s32 FILE_CreateTar(char *filename, char *src_path, u8 exclude_tar_files, u8 max_depth)
-
 
1465
{
-
 
1466
  s32 status = 0;
-
 
1467
-
 
1468
  if( !volume_available ) {
-
 
1469
#if DEBUG_VERBOSE_LEVEL >= 2
-
 
1470
    DEBUG_MSG("[FILE_CreateTar] ERROR: volume doesn't exist!\n");
-
 
1471
#endif
-
 
1472
    return FILE_ERR_NO_VOLUME;
-
 
1473
  }
-
 
1474
-
 
1475
  // convert filename to uppercase
-
 
1476
  {
-
 
1477
    char *filename_ptr = filename;
-
 
1478
    while( *filename_ptr != 0 ) {
-
 
1479
      *filename_ptr = toupper((int)*filename_ptr);
-
 
1480
      ++filename_ptr;
-
 
1481
    }
-
 
1482
  }
-
 
1483
-
 
1484
  // create file
-
 
1485
  if( (status=FILE_WriteOpen(filename, 1)) < 0 ) {
-
 
1486
#if DEBUG_VERBOSE_LEVEL >= 1
-
 
1487
    DEBUG_MSG("[FILE_CreateTar] ERROR: failed to create %s (error code: %d)!\n", filename, status);
-
 
1488
#endif
-
 
1489
    return status;
-
 
1490
  }
-
 
1491
-
 
1492
#if DEBUG_VERBOSE_LEVEL >= 1
-
 
1493
  DEBUG_MSG("[FILE_CreateTar] Creating %s for path: %s\n", filename, src_path);
-
 
1494
#endif
-
 
1495
-
 
1496
  // walk directory
-
 
1497
  u32 num_dirs = 1;
-
 
1498
  u32 num_files = 0;
-
 
1499
  status = FILE_CreateTarRecursive(filename, src_path, exclude_tar_files, 1, max_depth, &num_dirs, &num_files);
-
 
1500
-
 
1501
  if( status < 0 ) {
-
 
1502
    DEBUG_MSG("[FILE_CreateTar] failed with error code: %d\n", status);
-
 
1503
  } else {
-
 
1504
#if DEBUG_VERBOSE_LEVEL >= 1
-
 
1505
    DEBUG_MSG("[FILE_CreateTar] archived %d files in %d directories under %s (%d bytes)\n", num_dirs, num_files, filename, FILE_WriteGetCurrentSize());
-
 
1506
#endif
-
 
1507
  }
-
 
1508
-
 
1509
  // finalize file by adding two dummy all-zero blocks
-
 
1510
  {
-
 
1511
    u8 dummy[512];
-
 
1512
    memset(dummy, 0, 512);
-
 
1513
-
 
1514
    int i;
-
 
1515
    for(i=0; i<2; ++i) {
-
 
1516
      UINT successcount;  
-
 
1517
      if( (file_dfs_errno=f_write(&file_write, &dummy, 512, &successcount)) != FR_OK || successcount != 512 ) {
-
 
1518
#if DEBUG_VERBOSE_LEVEL >= 1
-
 
1519
    DEBUG_MSG("[FILE_CreateTar] Failed to write sector at position 0x%08x, status: %u\n", file_write.fptr, file_dfs_errno);
-
 
1520
#endif
-
 
1521
    status = FILE_ERR_WRITE;
-
 
1522
      }
-
 
1523
    }
-
 
1524
  }
-
 
1525
-
 
1526
  FILE_WriteClose();
-
 
1527
 
-
 
1528
  return status;
-
 
1529
}
-
 
1530
-
 
1531
-
 
1532
static s32 FILE_CreateTarHeader(char *filename, char *src_path, u8 is_dir, u32 filesize)
-
 
1533
{
-
 
1534
  s32 status = 0;
-
 
1535
  tar_posix_header *header;
-
 
1536
  header = (tar_posix_header *)&tmp_buffer;
-
 
1537
-
 
1538
#if TMP_BUFFER_SIZE != 512
-
 
1539
# error "We've a problem here!"
-
 
1540
#endif
-
 
1541
-
 
1542
  memset(header, 0, sizeof(header));
-
 
1543
-
 
1544
  strncpy(header->name, &filename[1], strlen(filename)-5); // remove initial / and .tar
-
 
1545
  header->name[strlen(filename)-5] = 0;
-
 
1546
  strcat(header->name, src_path);
-
 
1547
  if( is_dir ) {
-
 
1548
    strcat(header->name, "/");
-
 
1549
  }
-
 
1550
-
 
1551
  strcpy(header->mode, is_dir ? "000755 " : "000644 ");
-
 
1552
  strcpy(header->uid, "000000 ");
-
 
1553
  strcpy(header->gid, "000000 ");
-
 
1554
-
 
1555
  // filesize in octal format
-
 
1556
  {
-
 
1557
    int i;
-
 
1558
    for(i=0; i<11; ++i) {
-
 
1559
      header->size[i] = '0' + ((filesize >> 3*(10-i)) & 0x7);
-
 
1560
    }
-
 
1561
    header->size[11] = ' ';
-
 
1562
  }
-
 
1563
-
 
1564
  strcpy(header->mtime, "00000000000 ");
-
 
1565
  strcat(header->chksum, "        "); // will be calculated once header is complete
-
 
1566
  header->typeflag = is_dir ? '5' : '0';
-
 
1567
  //strcpy(header->linkname, "");
-
 
1568
  strcpy(header->magic, "ustar");
-
 
1569
  strcpy(header->version, "00");
-
 
1570
  strcpy(header->uname, "mios32");
-
 
1571
  strcpy(header->gname, "mios32");
-
 
1572
  strcat(header->devmajor, "000000 ");
-
 
1573
  strcpy(header->devminor, "000000 ");
-
 
1574
  //strcpy(header->prefix, "");
-
 
1575
-
 
1576
  {
-
 
1577
    u32 chksum = 0;
-
 
1578
    int i;
-
 
1579
    u8 *header_ptr = (u8 *)header;
-
 
1580
    for(i=0; i<512; ++i, header_ptr++) {
-
 
1581
      chksum += *header_ptr;
-
 
1582
    }
-
 
1583
-
 
1584
    // checksum in octal format
-
 
1585
    for(i=0; i<6; ++i) {
-
 
1586
      header->chksum[i] = '0' + ((chksum >> 3*(5-i)) & 0x7);
-
 
1587
    }
-
 
1588
    header->chksum[6] = 0;
-
 
1589
  }
-
 
1590
-
 
1591
-
 
1592
  UINT successcount;  
-
 
1593
  if( (file_dfs_errno=f_write(&file_write, header, 512, &successcount)) != FR_OK || successcount != 512 ) {
-
 
1594
#if DEBUG_VERBOSE_LEVEL >= 1
-
 
1595
    DEBUG_MSG("[FILE_CreateTarHeader] Failed to write sector at position 0x%08x, status: %u\n", file_write.fptr, file_dfs_errno);
-
 
1596
#endif
-
 
1597
    status = FILE_ERR_WRITE;
-
 
1598
  }
-
 
1599
-
 
1600
  return status;
-
 
1601
}
-
 
1602
-
 
1603
static s32 FILE_CreateTarRecursive(char *filename, char *src_path, u8 exclude_tar_files, u8 depth, u8 max_depth, u32 *num_dirs, u32 *num_files)
-
 
1604
{
-
 
1605
  s32 status = 0;
-
 
1606
-
 
1607
  DIR di;
-
 
1608
  FILINFO de;
-
 
1609
-
 
1610
  // format from https://www.gnu.org/software/tar/manual/html_node/Standard.html
-
 
1611
-
 
1612
  if( f_opendir(&di, src_path) != FR_OK ) {
-
 
1613
#if DEBUG_VERBOSE_LEVEL >= 1
-
 
1614
    DEBUG_MSG("[FILE_CreateTar] ERROR: couldn't open %s directory!\n", src_path);
-
 
1615
#endif
-
 
1616
    return FILE_ERR_NO_DIR;
-
 
1617
  }
-
 
1618
-
 
1619
  // create header for new directory
-
 
1620
  if( (status=FILE_CreateTarHeader(filename, src_path, 1, 0)) < 0 ) {
-
 
1621
    return status;
-
 
1622
  }
-
 
1623
-
 
1624
  while( status == 0 && f_readdir(&di, &de) == FR_OK && de.fname[0] != 0 ) {
-
 
1625
    char full_path[13 * (max_depth+1) + 1];
-
 
1626
    sprintf(full_path, "%s/%s", src_path, de.fname);
-
 
1627
-
 
1628
    if( de.fname[0] && de.fname[0] != '.' ) {
-
 
1629
      if( (de.fattrib & AM_DIR) && !(de.fattrib & AM_HID) ) {
-
 
1630
    *num_dirs += 1;
-
 
1631
-
 
1632
#if DEBUG_VERBOSE_LEVEL >= 1
-
 
1633
    DEBUG_MSG("[FILE_CreateTar] D %s\n", full_path);
-
 
1634
#endif
-
 
1635
    if( depth >= max_depth ) {
-
 
1636
#if DEBUG_VERBOSE_LEVEL >= 1
-
 
1637
      DEBUG_MSG("[FILE_CreateTar] Maximum depth of %d reached - won't go down further!\n", max_depth);
-
 
1638
#endif
-
 
1639
    } else {
-
 
1640
      status = FILE_CreateTarRecursive(filename, full_path, exclude_tar_files, depth+1, max_depth, num_dirs, num_files);
-
 
1641
      if( status < 0 )
-
 
1642
        break;
-
 
1643
    }
-
 
1644
      } else if( !(de.fattrib & AM_DIR) && !(de.fattrib & AM_HID) ) {
-
 
1645
    if( strcasecmp(de.fname, (char *)&filename[1]) == 0 ) {
-
 
1646
#if DEBUG_VERBOSE_LEVEL >= 1
-
 
1647
      DEBUG_MSG("[FILE_CreateTar] Skip %s (same file)\n", full_path);
-
 
1648
#endif
-
 
1649
    } else if( exclude_tar_files && strcasestr(de.fname, ".TAR") != 0 ) {
-
 
1650
#if DEBUG_VERBOSE_LEVEL >= 1
-
 
1651
      DEBUG_MSG("[FILE_CreateTar] Skip %s\n", full_path);
-
 
1652
#endif
-
 
1653
    } else {
-
 
1654
      *num_files += 1;
-
 
1655
#if DEBUG_VERBOSE_LEVEL >= 1
-
 
1656
      DEBUG_MSG("[FILE_CreateTar] F %s (%d bytes)\n", full_path, de.fsize);
-
 
1657
#endif
-
 
1658
-
 
1659
      // create header for new file
-
 
1660
      if( (status=FILE_CreateTarHeader(filename, full_path, 0, de.fsize)) < 0 ) {
-
 
1661
        return status;
-
 
1662
      }
-
 
1663
-
 
1664
      // copy file
-
 
1665
      if( (file_dfs_errno=f_open(&file_read, full_path, FA_OPEN_EXISTING | FA_READ)) != FR_OK ) {
-
 
1666
#if DEBUG_VERBOSE_LEVEL >= 1
-
 
1667
        DEBUG_MSG("[FILE_CreateTar] Failed to open %s!\n", full_path);
-
 
1668
#endif
-
 
1669
        return FILE_ERR_COPY_NO_FILE;
-
 
1670
      }
-
 
1671
-
 
1672
      UINT successcount;
-
 
1673
      UINT successcount_wr;
-
 
1674
      u32 num_bytes = 0;
-
 
1675
      do {
-
 
1676
        if( (file_dfs_errno=f_read(&file_read, tmp_buffer, TMP_BUFFER_SIZE, &successcount)) != FR_OK ) {
-
 
1677
#if DEBUG_VERBOSE_LEVEL >= 1
-
 
1678
          DEBUG_MSG("[FILE_CreateTar] Failed to read sector at position 0x%08x, status: %u\n", file_read.fptr, file_dfs_errno);
-
 
1679
#endif
-
 
1680
          successcount = 0;
-
 
1681
          status = FILE_ERR_READ;
-
 
1682
        } else if( successcount && (file_dfs_errno=f_write(&file_write, tmp_buffer, successcount, &successcount_wr)) != FR_OK ) {
-
 
1683
#if DEBUG_VERBOSE_LEVEL >= 1
-
 
1684
          DEBUG_MSG("[FILE_CreateTar] Failed to write sector at position 0x%08x, status: %u\n", file_write.fptr, file_dfs_errno);
-
 
1685
#endif
-
 
1686
          status = FILE_ERR_WRITE;
-
 
1687
        } else {
-
 
1688
          num_bytes += successcount_wr;
-
 
1689
        }
-
 
1690
      } while( status == 0 && successcount > 0 );
-
 
1691
-
 
1692
      if( status >= 0 && (de.fsize % 512) != 0 ) {
-
 
1693
        // fill remaining space
-
 
1694
        memset(tmp_buffer, 0, 512);
-
 
1695
        if( (file_dfs_errno=f_write(&file_write, tmp_buffer, 512 - (de.fsize % 512), &successcount_wr)) != FR_OK ) {
-
 
1696
#if DEBUG_VERBOSE_LEVEL >= 1
-
 
1697
          DEBUG_MSG("[FILE_CreateTar] Failed to write sector at position 0x%08x, status: %u\n", file_write.fptr, file_dfs_errno);
-
 
1698
#endif
-
 
1699
          status = FILE_ERR_WRITE;
-
 
1700
        }
-
 
1701
      }
-
 
1702
-
 
1703
      //f_close(&file_read); // never close read files to avoid "invalid object"
-
 
1704
-
 
1705
      if( status < 0 )
-
 
1706
        break;
-
 
1707
    }
-
 
1708
      }
-
 
1709
    }
-
 
1710
  }
-
 
1711
-
 
1712
  return status;
-
 
1713
}
-
 
1714
-
 
1715
-
 
1716
/////////////////////////////////////////////////////////////////////////////
-
 
1717
//! This function creates a backup file of the entire disk (except .tar files)
-
 
1718
//! Use this function to automatically determine the next backup file name
-
 
1719
//! Backup files are starting with "bak<number>.tar"
-
 
1720
/////////////////////////////////////////////////////////////////////////////
-
 
1721
s32 FILE_BackupDiskAutoName(u8 max_depth)
-
 
1722
{
-
 
1723
  int i;
-
 
1724
  for(i=1;;++i) {
-
 
1725
    char filename[20];
-
 
1726
    sprintf(filename, "/bak%d.tar", i);
-
 
1727
    s32 status = FILE_FileExists(filename);
-
 
1728
    if( status < 0 ) {
-
 
1729
#if DEBUG_VERBOSE_LEVEL >= 2
-
 
1730
      DEBUG_MSG("[FILE_BackupDiskAutoName] ERROR: during disk access, error code: %d!\n", status);
-
 
1731
#endif
-
 
1732
      return status;
-
 
1733
    }
-
 
1734
-
 
1735
    if( status == 0 ) {
-
 
1736
      return FILE_CreateTar(filename, "", 1, max_depth);
-
 
1737
    }
-
 
1738
  }
-
 
1739
-
 
1740
  return 0; // no error
-
 
1741
}
1428
1742
1429
/////////////////////////////////////////////////////////////////////////////
1743
/////////////////////////////////////////////////////////////////////////////
1430
//! This function prints some useful SD card informations on the MIOS terminal
1744
//! This function prints some useful SD card informations on the MIOS terminal
1431
/////////////////////////////////////////////////////////////////////////////
1745
/////////////////////////////////////////////////////////////////////////////
1432
s32 FILE_PrintSDCardInfos(void)
1746
s32 FILE_PrintSDCardInfos(void)