Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 2 additions & 148 deletions mkfs/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,161 +21,15 @@
*/

#include "mkexfat.h"
#include "vbr.h"
#include "fat.h"
#include "cbm.h"
#include "uct.h"
#include "rootdir.h"
#include <exfat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>

const struct fs_object* objects[] =
{
&vbr,
&vbr,
&fat,
/* clusters heap */
&cbm,
&uct,
&rootdir,
NULL,
};

static struct
{
int sector_bits;
int spc_bits;
off_t volume_size;
le16_t volume_label[EXFAT_ENAME_MAX + 1];
uint32_t volume_serial;
uint64_t first_sector;
}
param;

int get_sector_bits(void)
{
return param.sector_bits;
}

int get_spc_bits(void)
{
return param.spc_bits;
}

off_t get_volume_size(void)
{
return param.volume_size;
}

const le16_t* get_volume_label(void)
{
return param.volume_label;
}

uint32_t get_volume_serial(void)
{
return param.volume_serial;
}

uint64_t get_first_sector(void)
{
return param.first_sector;
}

int get_sector_size(void)
{
return 1 << get_sector_bits();
}

int get_cluster_size(void)
{
return get_sector_size() << get_spc_bits();
}

static int setup_spc_bits(int sector_bits, int user_defined, off_t volume_size)
{
int i;

if (user_defined != -1)
{
off_t cluster_size = 1 << sector_bits << user_defined;
if (volume_size / cluster_size > EXFAT_LAST_DATA_CLUSTER)
{
struct exfat_human_bytes chb, vhb;

exfat_humanize_bytes(cluster_size, &chb);
exfat_humanize_bytes(volume_size, &vhb);
exfat_error("cluster size %"PRIu64" %s is too small for "
"%"PRIu64" %s volume, try -s %d",
chb.value, chb.unit,
vhb.value, vhb.unit,
1 << setup_spc_bits(sector_bits, -1, volume_size));
return -1;
}
return user_defined;
}

if (volume_size < 256LL * 1024 * 1024)
return MAX(0, 12 - sector_bits); /* 4 KB */
if (volume_size < 32LL * 1024 * 1024 * 1024)
return MAX(0, 15 - sector_bits); /* 32 KB */

for (i = 17; ; i++) /* 128 KB or more */
if (DIV_ROUND_UP(volume_size, 1 << i) <= EXFAT_LAST_DATA_CLUSTER)
return MAX(0, i - sector_bits);
}

static int setup_volume_label(le16_t label[EXFAT_ENAME_MAX + 1], const char* s)
{
memset(label, 0, (EXFAT_ENAME_MAX + 1) * sizeof(le16_t));
if (s == NULL)
return 0;
return exfat_utf8_to_utf16(label, s, EXFAT_ENAME_MAX + 1, strlen(s));
}

static uint32_t setup_volume_serial(uint32_t user_defined)
{
struct timeval now;

if (user_defined != 0)
return user_defined;

if (gettimeofday(&now, NULL) != 0)
{
exfat_error("failed to form volume id");
return 0;
}
return (now.tv_sec << 20) | now.tv_usec;
}

static int setup(struct exfat_dev* dev, int sector_bits, int spc_bits,
const char* volume_label, uint32_t volume_serial,
uint64_t first_sector)
{
param.sector_bits = sector_bits;
param.first_sector = first_sector;
param.volume_size = exfat_get_size(dev);

param.spc_bits = setup_spc_bits(sector_bits, spc_bits, param.volume_size);
if (param.spc_bits == -1)
return 1;

if (setup_volume_label(param.volume_label, volume_label) != 0)
return 1;

param.volume_serial = setup_volume_serial(volume_serial);
if (param.volume_serial == 0)
return 1;

return mkfs(dev, param.volume_size);
}

static int logarithm2(int n)
{
size_t i;
Expand Down Expand Up @@ -242,7 +96,7 @@ int main(int argc, char* argv[])
dev = exfat_open(spec, EXFAT_MODE_RW);
if (dev == NULL)
return 1;
if (setup(dev, 9, spc_bits, volume_label, volume_serial,
if (exfat_mkfs(dev, 9, spc_bits, volume_label, volume_serial,
first_sector) != 0)
{
exfat_close(dev);
Expand Down
146 changes: 144 additions & 2 deletions mkfs/mkexfat.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,137 @@
*/

#include "mkexfat.h"
#include "vbr.h"
#include "fat.h"
#include "cbm.h"
#include "uct.h"
#include "rootdir.h"
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <inttypes.h>
#include <stdio.h>
#include <string.h>

static const struct fs_object* objects[] =
{
&vbr,
&vbr,
&fat,
/* clusters heap */
&cbm,
&uct,
&rootdir,
NULL,
};

static struct
{
int sector_bits;
int spc_bits;
off_t volume_size;
le16_t volume_label[EXFAT_ENAME_MAX + 1];
uint32_t volume_serial;
uint64_t first_sector;
}
param;

int get_sector_bits(void)
{
return param.sector_bits;
}

int get_spc_bits(void)
{
return param.spc_bits;
}

off_t get_volume_size(void)
{
return param.volume_size;
}

const le16_t* get_volume_label(void)
{
return param.volume_label;
}

uint32_t get_volume_serial(void)
{
return param.volume_serial;
}

uint64_t get_first_sector(void)
{
return param.first_sector;
}

int get_sector_size(void)
{
return 1 << get_sector_bits();
}

int get_cluster_size(void)
{
return get_sector_size() << get_spc_bits();
}

static int setup_spc_bits(int sector_bits, int user_defined, off_t volume_size)
{
int i;

if (user_defined != -1)
{
off_t cluster_size = 1 << sector_bits << user_defined;
if (volume_size / cluster_size > EXFAT_LAST_DATA_CLUSTER)
{
struct exfat_human_bytes chb, vhb;

exfat_humanize_bytes(cluster_size, &chb);
exfat_humanize_bytes(volume_size, &vhb);
exfat_error("cluster size %"PRIu64" %s is too small for "
"%"PRIu64" %s volume, try -s %d",
chb.value, chb.unit,
vhb.value, vhb.unit,
1 << setup_spc_bits(sector_bits, -1, volume_size));
return -1;
}
return user_defined;
}

if (volume_size < 256LL * 1024 * 1024)
return MAX(0, 12 - sector_bits); /* 4 KB */
if (volume_size < 32LL * 1024 * 1024 * 1024)
return MAX(0, 15 - sector_bits); /* 32 KB */

for (i = 17; ; i++) /* 128 KB or more */
if (DIV_ROUND_UP(volume_size, 1 << i) <= EXFAT_LAST_DATA_CLUSTER)
return MAX(0, i - sector_bits);
}

static int setup_volume_label(le16_t label[EXFAT_ENAME_MAX + 1], const char* s)
{
memset(label, 0, (EXFAT_ENAME_MAX + 1) * sizeof(le16_t));
if (s == NULL)
return 0;
return exfat_utf8_to_utf16(label, s, EXFAT_ENAME_MAX + 1, strlen(s));
}

static uint32_t setup_volume_serial(uint32_t user_defined)
{
struct timeval now;

if (user_defined != 0)
return user_defined;

if (gettimeofday(&now, NULL) != 0)
{
exfat_error("failed to form volume id");
return 0;
}
return (now.tv_sec << 20) | now.tv_usec;
}

static int check_size(off_t volume_size)
{
const struct fs_object** pp;
Expand Down Expand Up @@ -124,9 +249,26 @@ static int create(struct exfat_dev* dev)
return 0;
}

int mkfs(struct exfat_dev* dev, off_t volume_size)
int exfat_mkfs(struct exfat_dev* dev, int sector_bits, int spc_bits,
const char* volume_label, uint32_t volume_serial,
uint64_t first_sector)
{
if (check_size(volume_size) != 0)
param.sector_bits = sector_bits;
param.first_sector = first_sector;
param.volume_size = exfat_get_size(dev);

param.spc_bits = setup_spc_bits(sector_bits, spc_bits, param.volume_size);
if (param.spc_bits == -1)
return 1;

if (setup_volume_label(param.volume_label, volume_label) != 0)
return 1;

param.volume_serial = setup_volume_serial(volume_serial);
if (param.volume_serial == 0)
return 1;

if (check_size(param.volume_size) != 0)
return 1;

fputs("Creating... ", stdout);
Expand Down
6 changes: 3 additions & 3 deletions mkfs/mkexfat.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ struct fs_object
int (*write)(struct exfat_dev* dev);
};

extern const struct fs_object* objects[];

int get_sector_bits(void);
int get_spc_bits(void);
off_t get_volume_size(void);
Expand All @@ -43,7 +41,9 @@ uint64_t get_first_sector(void);
int get_sector_size(void);
int get_cluster_size(void);

int mkfs(struct exfat_dev* dev, off_t volume_size);
int exfat_mkfs(struct exfat_dev* dev, int sector_bits, int spc_bits,
const char* volume_label, uint32_t volume_serial,
uint64_t first_sector);
off_t get_position(const struct fs_object* object);

#endif /* ifndef MKFS_MKEXFAT_H_INCLUDED */