int do_format_with_create_data_file(const char *dev_dir, struct partition *partition)
{
uint8_t heads = 255;
uint8_t sect_per_clust = 64; /* fixed */
uint8_t check_sum = 0;
uint16_t reserved_sect = (uint16_t)sect_per_clust; /* fixed */
uint16_t bytes_per_sect = 0;
uint16_t sect_per_track = 63;
uint16_t fatents_per_sect = 0;
uint16_t fat_date = 0;
uint16_t fat_time = 0;
uint16_t backup_boot = 0;
uint16_t unicode_char = 0;
uint32_t sect_per_fat = 0;
uint32_t hidden_sect = 0;
uint32_t volume_id = 0;
uint32_t volume_size_sect = 0;
uint32_t total_sect = 0;
uint32_t total_clust = 0;
uint32_t occupy_clust_size = 0;
uint32_t clust_size = 0;
uint32_t cur_rootdir_clust = DEF_ROOTDIR_FIRST_CLUST;
uint32_t total_rootdir_clust = 0;
uint32_t next_clust = DEF_ROOTDIR_FIRST_CLUST + 1;
uint32_t entry_offset = 0; // offset in acurrent root dir clust
uint32_t total_file_num = 0;
uint32_t info_signature = 0x61417272; /* fixed, 0x61417272 ('rrAa') */
int ret = 0;
int sd_dev = -1;
int i = 0;
int j = 0;
int k = 0;
int name_len = 0;
unsigned char *fat_buf = NULL;
time_t t;
struct tm tm_time;
char *prefix_name = get_data_file_prefix();
char name[SHORT_NAME_PREFIX_LEN + 1] = {0};
char short_name[SHORT_NAME_LEN] = {0};
char long_name[256] = {0};
struct sd_device_info devinfo = {0};
struct msdos_boot_sector bs = {{0}};
struct msdos_dir_entry entry = {{0}};
struct msdos_dir_long_entry long_entry = {0};
struct timespan ts = {0, 0};
if (dev_dir == NULL || partition == NULL)
{
STM_ERROR("This disk have been deleted.");
return -1;
}
sd_dev = open(dev_dir, O_EXCL | O_RDWR);
if (sd_dev < 0)
{
STM_ERROR("can't open %s.", dev_dir);
ret = -1;
goto out;
}
if (get_sd_device_info(sd_dev, &devinfo) < 0)
{
STM_ERROR("error collecting information about %s", dev_dir);
ret = -1;
goto out;
}
if (devinfo.size <= 0)
{
STM_ERROR("unable to discover size of %s", dev_dir);
ret = -1;
goto out;
}
if (devinfo.sector_size > 4096 || devinfo.sector_size <= 0)
{
STM_ERROR("sector size %d is non-standard, filesystem not be usable.", devinfo.sector_size);
ret = -1;
goto out;
}
bytes_per_sect = (uint16_t)(devinfo.sector_size);
fatents_per_sect = bytes_per_sect / FAT32_ENTRY_SIZE; // clust num per sector in FAT
volume_size_sect = (uint32_t)(devinfo.size / bytes_per_sect);
clust_size = (uint32_t)(bytes_per_sect * sect_per_clust);
if (clust_size > 32 * 1024)
{
STM_ERROR("clust size %d > 32K is non-standard, filesystem not be usable.", clust_size);
ret = -1;
goto out;
}
if (devinfo.size < 512 * 1024 * 1024)
{
/*
* These values are more or less meaningless, but we can at least
* use less extreme values for smaller filesystems where the large
* dummy values signifying LBA only access are not needed.
*/
sect_per_track = 32;
heads = 64;
}
if (devinfo.geom_heads > 0)
{
heads = devinfo.geom_heads;
sect_per_track = devinfo.geom_sectors;
}
if (devinfo.geom_start >= 0)
{
hidden_sect = htole32(devinfo.geom_start);
}
fat_buf = (unsigned char *)malloc(bytes_per_sect);
if (fat_buf == NULL)
{
STM_ERROR("malloc fat_buf failed.");
ret = -1;
goto out;
}
backup_boot = (reserved_sect >= 7) ? 6 : ((reserved_sect >= 2) ? (reserved_sect - 1) : 0);
/* setup table */
bs.boot_jump_and_sys_id[0] = 0xeb;
bs.boot_jump_and_sys_id[1] = 0x58;
bs.boot_jump_and_sys_id[2] = 0x90;
memcpy(&bs.boot_jump_and_sys_id[3], "mkfs.fat", 8); /* fixed */
STORE_LE(bs.bytes_per_sect, bytes_per_sect);
STORE_LE(bs.sect_per_clust, sect_per_clust); /* fixed */
STORE_LE(bs.reserved_sect, reserved_sect); /* fixed */
STORE_LE(bs.fats, 2); /* fixed */
STORE_LE(bs.dir_entries, 0); /* for FAT32, stays 0 */
STORE_LE(bs.volume_size_sect, 0); /* fixed */
STORE_LE(bs.media_byte, 0xf8); /* fixed */
STORE_LE(bs.sect_per_fat, 0); /* fixed */
STORE_LE(bs.sect_per_track, sect_per_track);
STORE_LE(bs.heads, heads);
STORE_LE(bs.hidden, hidden_sect);
STORE_LE(bs.fat32_volume_size_sect, volume_size_sect);
//STORE_LE(bs.fat32_sect_per_fat, );
STORE_LE(bs.fat32_flags, 0); /* fixed */
STORE_LE(bs.fat32_version[0], 0); /* fixed */
STORE_LE(bs.fat32_version[1], 0); /* fixed */
STORE_LE(bs.fat32_root_cluster, cur_rootdir_clust); /* fixed */
STORE_LE(bs.fat32_info_sector, 1); /* fixed */
STORE_LE(bs.fat32_backup_boot, backup_boot); /* fixed */
STORE_LE(bs.vi.drive_number, 0x80); /* fixed */
STORE_LE(bs.vi.ext_boot_sign, 0x29); /* fixed */
volume_id = time(NULL);
STORE_LE(bs.vi.volume_id32, volume_id);
strncpy(bs.vi.volume_label, "NO NAME ", sizeof(bs.vi.volume_label)); /* fixed */
strncpy(bs.vi.fs_type, "FAT32 ", sizeof(bs.vi.fs_type)); /* fixed */
int offset = (char *)&bs.boot_code - (char *)&bs + MESSAGE_OFFSET + 0x7c00;
dummy_boot_code[BOOTCODE_FAT32_SIZE - 1] = 0;
memcpy(bs.boot_code, dummy_boot_code, BOOTCODE_FAT32_SIZE);
bs.boot_code[MSG_OFFSET_OFFSET] = offset & 0xff;
bs.boot_code[MSG_OFFSET_OFFSET + 1] = offset >> 8;
STORE_LE(bs.boot_sign, BOOT_SIGN);
if ((long long)(devinfo.size / bytes_per_sect) > 0xFFFFFFFF)
{
STM_ERROR("sd card size(%lld) is to large.", devinfo.size);
ret = -1;
goto out;
}
total_sect = volume_size_sect - align_object(reserved_sect, bs.sect_per_clust);
total_clust = ((long long)total_sect * bytes_per_sect + 2 * 8) /
((int)sect_per_clust * bytes_per_sect + 2 * 4);
sect_per_fat = align_object(cdiv((total_clust + 2) * 4, bytes_per_sect),
sect_per_clust);
/* Need to recalculate number of clusters, since the unused parts of the
* FATS and data area together could make up space for an additional,
* not really present cluster. */
total_clust = (total_sect - 2 * sect_per_fat) / sect_per_clust;
if (((sect_per_fat * bytes_per_sect) / 4) > MAX_CLUST_32)
{
STM_ERROR("sd card size(%lld) is to large.", devinfo.size);;
ret = -1;
goto out;
}
STORE_LE(bs.fat32_sect_per_fat, sect_per_fat);
{
printf("%s has %d head%s and %d sector%s per track,\n",
dev_dir, le16toh(bs.heads),
(le16toh(bs.heads) != 1) ? "s" : "", le16toh(bs.sect_per_track),
(le16toh(bs.sect_per_track) != 1) ? "s" : "");
printf("hidden sectors 0x%04x;\n", hidden_sect);
printf("logical sector size is %d,\n", bytes_per_sect);
printf("using 0x%02x media descriptor, with %u sectors;\n",
(int)(bs.media_byte), volume_size_sect);
printf("drive number 0x%02x;\n", (int)(bs.vi.drive_number));
printf("filesystem has %d 32-bit FAT%s and %d sector%s per cluster.\n",
(int)(bs.fats), (bs.fats != 1) ? "s" : "",
(int)(bs.sect_per_clust), (bs.sect_per_clust != 1) ? "s" : "");
printf("FAT size is %d sector%s, and provides %u cluster%s.\n",
(int)sect_per_fat, (sect_per_fat != 1) ? "s" : "",
total_clust, (total_clust != 1) ? "s" : "");
printf("There %s %u reserved sector%s.\n",
(reserved_sect != 1) ? "are" : "is",
reserved_sect, (reserved_sect != 1) ? "s" : "");
}
memset(fat_buf, 0, bytes_per_sect);
/* write msdos_boot_sector */
for (i = 0; i < reserved_sect; i++)
{
lseek(sd_dev, (i * bytes_per_sect), SEEK_SET);
xwrite(sd_dev, fat_buf, bytes_per_sect);
}
lseek(sd_dev, 0, SEEK_SET);
xwrite(sd_dev, (char *)&bs, sizeof(struct msdos_boot_sector));
lseek(sd_dev, (backup_boot * bytes_per_sect), SEEK_SET);
xwrite(sd_dev, (char *)&bs, sizeof(struct msdos_boot_sector));
/* update FAT and rootdir */
memset(fat_buf, 0, bytes_per_sect);
#define FAT1_CLUST_OFFSET(clust) (reserved_sect * bytes_per_sect + (clust) * FAT32_ENTRY_SIZE)
#define FAT2_CLUST_OFFSET(clust) ((reserved_sect + sect_per_fat) * bytes_per_sect + (clust) * FAT32_ENTRY_SIZE)
#define UPDATE_FAT(buffer, clust, num) \
do \
{ \
lseek(sd_dev, FAT1_CLUST_OFFSET(clust), SEEK_SET); \
xwrite(sd_dev, (buffer), (num) * FAT32_ENTRY_SIZE); \
lseek(sd_dev, FAT2_CLUST_OFFSET(clust), SEEK_SET); \
xwrite(sd_dev, (buffer), (num) * FAT32_ENTRY_SIZE); \
}while(0)
#define UPDATE_FAT_IF_BUF_FULL(clust) \
do \
{ \
if(((clust) % fatents_per_sect) == 0) \
{ \
UPDATE_FAT(fat_buf, ((clust) - fatents_per_sect), fatents_per_sect); \
memset(fat_buf, 0, bytes_per_sect); \
} \
}while(0)
#define CLUST_OFFSET(clust) ((reserved_sect + bs.fats * sect_per_fat) * bytes_per_sect + ((clust) - 2) * clust_size)
#define ENTRY_OFFSET(offset) (CLUST_OFFSET(cur_rootdir_clust) + (offset))
#define ADD_LONG_ENTRY(long_name, short_name, file_size, file_date, file_time) \
do \
{ \
occupy_clust_size = 0; \
if(entry_offset >= clust_size) \
{ \
/* next clust for root dir */ \
entry_offset -= clust_size; \
++cur_rootdir_clust; \
} \
check_sum = 0; \
for (j = 0; j < SHORT_NAME_LEN; j++) \
{ \
check_sum = ((check_sum & 1) ? 0x80 : 0) + (check_sum >> 1) + short_name[j]; \
} \
name_len = strlen(long_name); \
for (j = cdiv(name_len, LONG_ENTRY_UNICODE_NUM); j > 0; j--) \
{ \
memset(&long_entry, 0, sizeof(long_entry)); \
if (j == cdiv(name_len, LONG_ENTRY_UNICODE_NUM)) \
{ \
STORE_LE(long_entry.index, 0x40 | (uint8_t)j); \
} \
else \
{ \
STORE_LE(long_entry.index, (uint8_t)j); \
} \
for (k = 0; k < LONG_ENTRY_UNICODE_NUM; k++) \
{ \
if (((j - 1) * LONG_ENTRY_UNICODE_NUM + k) == name_len) \
{ \
unicode_char = 0x0000; \
} \
else if (((j - 1) * LONG_ENTRY_UNICODE_NUM + k) > name_len) \
{ \
unicode_char = 0xFFFF; \
} \
else \
{ \
unicode_char = (uint16_t)long_name[(j - 1) * LONG_ENTRY_UNICODE_NUM + k]; \
} \
if (k < LONG_ENTRY_UNICODE1_NUM) \
{ \
STORE_LE(long_entry.unicode1[k], unicode_char); \
} \
else if (k < (LONG_ENTRY_UNICODE1_NUM + LONG_ENTRY_UNICODE2_NUM)) \
{ \
STORE_LE(long_entry.unicode2[k - LONG_ENTRY_UNICODE1_NUM], unicode_char); \
} \
else \
{ \
STORE_LE(long_entry.unicode3[k - (LONG_ENTRY_UNICODE1_NUM + LONG_ENTRY_UNICODE2_NUM)], unicode_char); \
} \
} \
STORE_LE(long_entry.attr, ATTR_LONG_ENTRY); \
STORE_LE(long_entry.start, 0x0); \
STORE_LE(long_entry.checksum, check_sum); \
/* write long entry */ \
lseek(sd_dev, ENTRY_OFFSET(entry_offset), SEEK_SET); \
xwrite(sd_dev, &long_entry, sizeof(struct msdos_dir_long_entry)); \
entry_offset += sizeof(struct msdos_dir_long_entry); \
} \
memcpy(entry.name, short_name, sizeof(entry.name)); \
STORE_LE(entry.attr, ATTR_ARCH); \
STORE_LE(entry.lcase, 0); \
STORE_LE(entry.ctime_cs, 100); \
STORE_LE(entry.ctime, file_time); \
STORE_LE(entry.cdate, file_date); \
STORE_LE(entry.adate, file_date); \
STORE_LE(entry.starthi,((next_clust >> 16) & 0xffff) ); \
STORE_LE(entry.time, file_time); \
STORE_LE(entry.date, file_date); \
STORE_LE(entry.start,(next_clust & 0xffff) ); \
STORE_LE(entry.size, file_size); \
/* allocate clust for File */ \
occupy_clust_size = ((file_size + clust_size - 1 ) / clust_size); \
for(j = 0; j < occupy_clust_size ;j++) \
{ \
if( j < (occupy_clust_size - 1) ) \
{ \
MARK_CLUSTER(next_clust % fatents_per_sect, next_clust + 1); \
} \
else \
{ \
MARK_CLUSTER(next_clust % fatents_per_sect, EOF_FAT32); \
} \
++next_clust; \
UPDATE_FAT_IF_BUF_FULL(next_clust); \
} \
/* write file entry */ \
lseek(sd_dev, ENTRY_OFFSET(entry_offset), SEEK_SET); \
xwrite(sd_dev, &entry, sizeof(struct msdos_dir_entry)); \
entry_offset += sizeof(struct msdos_dir_entry); \
} while(0)
#define MARK_CLUSTER(cluster, value) \
((uint32_t *)fat_buf)[cluster] = htole32(value)
memset(fat_buf, 0, bytes_per_sect);
// initial FAT entries
MARK_CLUSTER(0, 0x0fffff00 | bs.media_byte);
MARK_CLUSTER(1, 0xffffffff);
// mark cluster 2 as EOF (used for root dir)
//MARK_CLUSTER(2, EOF_FAT32);
/* 需要创建的文件总的个数,各分区文件数量和 */
total_file_num = partition->files_info.data_file_num + partition->files_info.pic_file_num;
STM_INFO("total_file_num = %u", total_file_num);
/* 根目录需要占用的簇的个数
* 以目前命名方式一个文件名占用的目录项最大为4条(每条32字节),
* 算出总占用字节数,再以簇的字节数做对齐操作 */
total_rootdir_clust = ((4 * total_file_num * sizeof(struct msdos_dir_entry) + clust_size - 1) / clust_size);
if(0 == total_rootdir_clust)
{
total_rootdir_clust = 1;
}
for(i = 2 ; i < (total_rootdir_clust + 2); i++ )
{
if( i < (total_rootdir_clust + 2 - 1) )
{
MARK_CLUSTER(i % fatents_per_sect, i + 1);
}
else
{
MARK_CLUSTER(i % fatents_per_sect, EOF_FAT32);
}
UPDATE_FAT_IF_BUF_FULL(i);
}
next_clust = i;
/* init file time */
time(&t);
localtime_r(&t, &tm_time);
fat_time = (tm_time.tm_sec >> 1) + (tm_time.tm_min << 5) + (tm_time.tm_hour << 11);
fat_date = tm_time.tm_mday + ((tm_time.tm_mon+1) << 5) + ((tm_time.tm_year - 80) << 9);
if (!get_file_prefix_inited_flag())
{
init_data_file_prefix();
}
int idx;
char *postfix = "mp4";
uint32_t data_file_size = partition->files_info.data_file_size;
uint32_t data_file_num = partition->files_info.data_file_num;
for (idx = DISK_PRECREATE_START; idx < DISK_PRECREATE_END; idx++)
{
if (idx == DISK_PRECREATE_PIC)
{
postfix = "pic";
data_file_num = partition->files_info.pic_file_num;
}
#ifdef SPLENDID_MOMENT
else if (idx == DISK_PRECREATE_SPLMOM)
{
uint64_t splmom_total_space = 0;
postfix = SPLMOM_MEDIA_FILE_POSFIX;
splmom_get_total_space(&splmom_total_space);
data_file_num = splmom_total_space / SPLMOM_MEDIA_FILE_SIZE;
data_file_size = SPLMOM_MEDIA_FILE_SIZE;
}
#endif
STM_INFO("Creating data %u %s ...", data_file_num, postfix);
for(i = 0; i < data_file_num; i++)
{
memset(long_name, 0, sizeof(long_name));
if (idx == DISK_PRECREATE_RECORD)
{
ts.start_time = 0;
ts.end_time = 0;
ret = get_data_file_name_with_time(i, &ts, postfix, long_name, sizeof(long_name));
}
#ifdef SPLENDID_MOMENT
else if (idx == DISK_PRECREATE_SPLMOM)
{
MEDIAFILE_PATH_PARAMS param = {0};
param.type = MEDIAFILE_PATH_TYPE_DEF;
param.id = i;
param.b_onlyname = 1;
ret = splmom_get_mediafile_path(¶m, long_name, sizeof(long_name));
}
#endif
else
{
ret = get_data_file_name(i, postfix, long_name, sizeof(long_name));
}
if (ret < 0)
{
continue;
}
// STM_INFO("create file %s.%s", long_name, postfix);
if ((strlen(long_name) <= sizeof(entry.name) + 1) &&
(strlen(postfix) <= SHORT_NAME_POSTFIX_LEN))
{
/* 文件名长度符合8+3规则时的命名规则 */
/* init short name */
memset(name, 0, sizeof(name));
memset(short_name, 0x20, sizeof(short_name));
snprintf(name, sizeof(name), "%s%05d", prefix_name, i);
memcpy(short_name, name, strlen(name));
memcpy(short_name + SHORT_NAME_PREFIX_LEN, postfix, SHORT_NAME_POSTFIX_LEN);
for (j = 0; j < SHORT_NAME_LEN; j++)
{
short_name[j] = TOUPPER(short_name[j]);
}
ADD_LONG_ENTRY(long_name, short_name, data_file_size, fat_date, fat_time);
}
else
{
/* init short name */
short_name[0] = TOUPPER(long_name[0]);
short_name[1] = TOUPPER(long_name[1]);
snprintf(&short_name[2], SHORT_NAME_PREFIX_LEN, "%04d", i);
short_name[6] = 0x7E;
short_name[7] = '1';
memcpy(short_name + SHORT_NAME_PREFIX_LEN, postfix, SHORT_NAME_POSTFIX_LEN);
for (j = SHORT_NAME_PREFIX_LEN; j < SHORT_NAME_LEN; j++)
{
short_name[j] = TOUPPER(short_name[j]);
}
ADD_LONG_ENTRY(long_name, short_name, data_file_size, fat_date, fat_time);
}
}
}
printf("--- total_rootdir_clust:%u offset:%u root_clust:%u next_clust:%u---\n",
total_rootdir_clust, entry_offset, cur_rootdir_clust, next_clust);
//FAT
/* update buffer FAT */
if (next_clust % fatents_per_sect)
{
UPDATE_FAT(fat_buf, (next_clust - (next_clust % fatents_per_sect)), fatents_per_sect);
}
memset(fat_buf, 0, bytes_per_sect);
/* a set of zero bytes for remaining FAT. */
i = (next_clust / fatents_per_sect) + ((next_clust % fatents_per_sect) ? 1 : 0);
for ( ;i < sect_per_fat; i++)
{
UPDATE_FAT(fat_buf, i * fatents_per_sect, fatents_per_sect);
}
// root directory
// empty directory is just a set of zero bytes
lseek(sd_dev, ENTRY_OFFSET(entry_offset), SEEK_SET);
for (; cur_rootdir_clust < total_rootdir_clust + 2; cur_rootdir_clust++)
{
for (i = entry_offset; i < clust_size;)
{
if (i % bytes_per_sect)
{
xwrite(sd_dev, fat_buf, bytes_per_sect - (i % bytes_per_sect));
i += (bytes_per_sect - (i % bytes_per_sect));
}
else
{
xwrite(sd_dev, fat_buf , bytes_per_sect);
i += bytes_per_sect;
}
}
entry_offset = 0;
}
/* write info_sector */
memset(fat_buf, 0, bytes_per_sect);
struct info_sector *info = (struct info_sector *)fat_buf;
/* Info sector magic */
memcpy((char *)&info->magic, "RRaA", 4);
STORE_LE(info->signature, info_signature);
STORE_LE(info->free_clusters, (total_clust - next_clust + 1));
STORE_LE(info->next_cluster, next_clust);
STORE_LE(info->boot_sign, BOOT_SIGN);
lseek(sd_dev, (le16toh(bs.fat32_info_sector) * bytes_per_sect), SEEK_SET);
xwrite(sd_dev, (char *)info, bytes_per_sect);
out:
if (sd_dev >= 0)
{
close(sd_dev);
sd_dev = -1;
}
if (fat_buf != NULL)
{
free(fat_buf);
fat_buf = NULL;
}
return ret;
}
代码的功能是什么
最新发布