$(top_srcdir)/build-aux/install-sh \
$(top_srcdir)/build-aux/ltmain.sh \
$(top_srcdir)/build-aux/missing COPYING NEWS build-aux/compile \
- build-aux/config.guess build-aux/config.sub build-aux/depcomp \
+ build-aux/config.guess build-aux/config.sub \
build-aux/install-sh build-aux/ltmain.sh build-aux/missing
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
+exfatprogs 1.1.2 - released 2021-05-20
+======================================
+
+CHANGES :
+ * mkfs.exfat: set 0x80 to DriveSelect of the boot sector
+
+BUG FIXES :
+ * Fix issues on 4KB logical sector devices
+ * Fix issues when the sector size of of a file system is different from
+ that of a block device.
+
exfatprogs 1.1.1 - released 2021-04-21
======================================
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for exfatprogs 1.1.1.
+# Generated by GNU Autoconf 2.69 for exfatprogs 1.1.2.
#
# Report bugs to <linkinjeon@kernel.org>.
#
# Identity of this package.
PACKAGE_NAME='exfatprogs'
PACKAGE_TARNAME='exfatprogs'
-PACKAGE_VERSION='1.1.1'
-PACKAGE_STRING='exfatprogs 1.1.1'
+PACKAGE_VERSION='1.1.2'
+PACKAGE_STRING='exfatprogs 1.1.2'
PACKAGE_BUGREPORT='linkinjeon@kernel.org'
PACKAGE_URL='https://github.com/exfatprogs/exfatprogs'
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures exfatprogs 1.1.1 to adapt to many kinds of systems.
+\`configure' configures exfatprogs 1.1.2 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of exfatprogs 1.1.1:";;
+ short | recursive ) echo "Configuration of exfatprogs 1.1.2:";;
esac
cat <<\_ACEOF
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-exfatprogs configure 1.1.1
+exfatprogs configure 1.1.2
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by exfatprogs $as_me 1.1.1, which was
+It was created by exfatprogs $as_me 1.1.2, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
# Define the identity of the package.
PACKAGE='exfatprogs'
- VERSION='1.1.1'
+ VERSION='1.1.2'
cat >>confdefs.h <<_ACEOF
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by exfatprogs $as_me 1.1.1, which was
+This file was extended by exfatprogs $as_me 1.1.2, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-exfatprogs config.status 1.1.1
+exfatprogs config.status 1.1.2
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
unsigned char *bitmap;
char *volume_label;
- ppbr = malloc(bd->sector_size);
+ ppbr = malloc(EXFAT_MAX_SECTOR_SIZE);
if (!ppbr) {
exfat_err("Cannot allocate pbr: out of memory\n");
return -ENOMEM;
}
/* read main boot sector */
- ret = exfat_read_sector(bd, (char *)ppbr, BOOT_SEC_IDX);
- if (ret < 0) {
+ if (exfat_read(bd->dev_fd, (char *)ppbr, EXFAT_MAX_SECTOR_SIZE,
+ 0) != (ssize_t)EXFAT_MAX_SECTOR_SIZE) {
exfat_err("main boot sector read failed\n");
ret = -EIO;
goto free_ppbr;
goto free_ppbr;
}
- if (bd->sector_size != 1 << pbsx->sect_size_bits) {
- exfat_err("bogus sector size : %u (sector size bits : %u)\n",
- bd->sector_size, pbsx->sect_size_bits);
- ret = -EINVAL;
- goto free_ppbr;
- }
+ bd->sector_size_bits = pbsx->sect_size_bits;
+ bd->sector_size = 1 << pbsx->sect_size_bits;
clu_offset = le32_to_cpu(pbsx->clu_offset);
total_clus = le32_to_cpu(pbsx->clu_count);
exfat->bs->bsx.sect_per_clus_bits));
}
-static int boot_region_checksum(struct exfat_blk_dev *bd, int bs_offset)
+static int boot_region_checksum(int dev_fd,
+ int bs_offset, unsigned int sect_size)
{
void *sect;
unsigned int i;
uint32_t checksum;
int ret = 0;
- unsigned int size;
- size = bd->sector_size;
- sect = malloc(size);
+ sect = malloc(sect_size);
if (!sect)
return -ENOMEM;
checksum = 0;
for (i = 0; i < 11; i++) {
- if (exfat_read(bd->dev_fd, sect, size,
- bs_offset * size + i * size) !=
- (ssize_t)size) {
+ if (exfat_read(dev_fd, sect, sect_size,
+ bs_offset * sect_size + i * sect_size) !=
+ (ssize_t)sect_size) {
exfat_err("failed to read boot region\n");
ret = -EIO;
goto out;
}
- boot_calc_checksum(sect, size, i == 0, &checksum);
+ boot_calc_checksum(sect, sect_size, i == 0, &checksum);
}
- if (exfat_read(bd->dev_fd, sect, size,
- bs_offset * size + 11 * size) !=
- (ssize_t)size) {
+ if (exfat_read(dev_fd, sect, sect_size,
+ bs_offset * sect_size + 11 * sect_size) !=
+ (ssize_t)sect_size) {
exfat_err("failed to read a boot checksum sector\n");
ret = -EIO;
goto out;
}
- for (i = 0; i < size/sizeof(checksum); i++) {
+ for (i = 0; i < sect_size/sizeof(checksum); i++) {
if (le32_to_cpu(((__le32 *)sect)[i]) != checksum) {
exfat_err("checksum of boot region is not correct. %#x, but expected %#x\n",
le32_to_cpu(((__le32 *)sect)[i]), checksum);
}
static int read_boot_region(struct exfat_blk_dev *bd, struct pbr **pbr,
- int bs_offset)
+ int bs_offset, unsigned int sect_size,
+ bool verbose)
{
struct pbr *bs;
int ret = -EINVAL;
}
if (exfat_read(bd->dev_fd, bs, sizeof(*bs),
- bs_offset * bd->sector_size) != (ssize_t)sizeof(*bs)) {
+ bs_offset * sect_size) != (ssize_t)sizeof(*bs)) {
exfat_err("failed to read a boot sector\n");
ret = -EIO;
goto err;
}
if (memcmp(bs->bpb.oem_name, "EXFAT ", 8) != 0) {
- exfat_err("failed to find exfat file system.\n");
+ if (verbose)
+ exfat_err("failed to find exfat file system\n");
goto err;
}
- ret = boot_region_checksum(bd, bs_offset);
+ ret = boot_region_checksum(bd->dev_fd, bs_offset, sect_size);
if (ret < 0)
goto err;
ret = -EINVAL;
if (EXFAT_SECTOR_SIZE(bs) < 512 || EXFAT_SECTOR_SIZE(bs) > 4 * KB) {
- exfat_err("too small or big sector size: %d\n",
- EXFAT_SECTOR_SIZE(bs));
+ if (verbose)
+ exfat_err("too small or big sector size: %d\n",
+ EXFAT_SECTOR_SIZE(bs));
goto err;
}
if (EXFAT_CLUSTER_SIZE(bs) > 32 * MB) {
- exfat_err("too big cluster size: %d\n", EXFAT_CLUSTER_SIZE(bs));
+ if (verbose)
+ exfat_err("too big cluster size: %d\n",
+ EXFAT_CLUSTER_SIZE(bs));
goto err;
}
if (bs->bsx.fs_version[1] != 1 || bs->bsx.fs_version[0] != 0) {
- exfat_err("unsupported exfat version: %d.%d\n",
- bs->bsx.fs_version[1], bs->bsx.fs_version[0]);
+ if (verbose)
+ exfat_err("unsupported exfat version: %d.%d\n",
+ bs->bsx.fs_version[1], bs->bsx.fs_version[0]);
goto err;
}
if (bs->bsx.num_fats != 1) {
- exfat_err("unsupported FAT count: %d\n", bs->bsx.num_fats);
+ if (verbose)
+ exfat_err("unsupported FAT count: %d\n",
+ bs->bsx.num_fats);
goto err;
}
if (le64_to_cpu(bs->bsx.vol_length) * EXFAT_SECTOR_SIZE(bs) >
bd->size) {
- exfat_err("too large sector count: %" PRIu64 ", expected: %llu\n",
- le64_to_cpu(bs->bsx.vol_length),
- bd->num_sectors);
+ if (verbose)
+ exfat_err("too large sector count: %" PRIu64 ", expected: %llu\n",
+ le64_to_cpu(bs->bsx.vol_length),
+ bd->num_sectors);
goto err;
}
if (le32_to_cpu(bs->bsx.clu_count) * EXFAT_CLUSTER_SIZE(bs) >
bd->size) {
- exfat_err("too large cluster count: %u, expected: %u\n",
- le32_to_cpu(bs->bsx.clu_count),
- bd->num_clusters);
+ if (verbose)
+ exfat_err("too large cluster count: %u, expected: %u\n",
+ le32_to_cpu(bs->bsx.clu_count),
+ bd->num_clusters);
goto err;
}
return ret;
}
-static int restore_boot_region(struct exfat_blk_dev *bd)
+static int restore_boot_region(struct exfat_blk_dev *bd, unsigned int sect_size)
{
int i;
char *sector;
int ret;
- sector = malloc(bd->sector_size);
+ sector = malloc(sect_size);
if (!sector)
return -ENOMEM;
for (i = 0; i < 12; i++) {
- if (exfat_read(bd->dev_fd, sector, bd->sector_size,
- BACKUP_BOOT_SEC_IDX * bd->sector_size +
- i * bd->sector_size) !=
- (ssize_t)bd->sector_size) {
+ if (exfat_read(bd->dev_fd, sector, sect_size,
+ BACKUP_BOOT_SEC_IDX * sect_size +
+ i * sect_size) !=
+ (ssize_t)sect_size) {
ret = -EIO;
goto free_sector;
}
if (i == 0)
((struct pbr *)sector)->bsx.perc_in_use = 0xff;
- if (exfat_write(bd->dev_fd, sector, bd->sector_size,
- BOOT_SEC_IDX * bd->sector_size +
- i * bd->sector_size) !=
- (ssize_t)bd->sector_size) {
+ if (exfat_write(bd->dev_fd, sector, sect_size,
+ BOOT_SEC_IDX * sect_size +
+ i * sect_size) !=
+ (ssize_t)sect_size) {
ret = -EIO;
goto free_sector;
}
static int exfat_boot_region_check(struct exfat *exfat, struct pbr **bs)
{
+ struct pbr *boot_sect;
+ unsigned int sect_size;
int ret;
- ret = read_boot_region(exfat->blk_dev, bs, BOOT_SEC_IDX);
+ /* First, find out the exfat sector size */
+ boot_sect = malloc(sizeof(*boot_sect));
+ if (boot_sect == NULL)
+ return -ENOMEM;
+
+ if (exfat_read(exfat->blk_dev->dev_fd, boot_sect,
+ sizeof(*boot_sect), 0) != (ssize_t)sizeof(*boot_sect)) {
+ exfat_err("failed to read Main boot sector\n");
+ return -EIO;
+ }
+
+ sect_size = 1 << boot_sect->bsx.sect_size_bits;
+ free(boot_sect);
+
+ /* check boot regions */
+ ret = read_boot_region(exfat->blk_dev, bs,
+ BOOT_SEC_IDX, sect_size, true);
if (ret == -EINVAL && exfat_repair_ask(exfat, ER_BS_BOOT_REGION,
"boot region is corrupted. try to restore the region from backup"
)) {
- ret = read_boot_region(exfat->blk_dev, bs, BACKUP_BOOT_SEC_IDX);
- if (ret < 0) {
- exfat_err("backup boot region is also corrupted\n");
- return ret;
+ const unsigned int sector_sizes[] = {512, 4096, 1024, 2048};
+ unsigned int i;
+
+ if (sect_size >= 512 && sect_size <= EXFAT_MAX_SECTOR_SIZE) {
+ ret = read_boot_region(exfat->blk_dev, bs,
+ BACKUP_BOOT_SEC_IDX, sect_size,
+ false);
+ if (!ret)
+ goto restore;
}
- ret = restore_boot_region(exfat->blk_dev);
- if (ret < 0) {
- exfat_err("failed to restore boot region from backup\n");
- free(*bs);
- *bs = NULL;
- return ret;
+
+ for (i = 0; i < sizeof(sector_sizes)/sizeof(sector_sizes[0]); i++) {
+ if (sector_sizes[i] == sect_size)
+ continue;
+
+ ret = read_boot_region(exfat->blk_dev, bs,
+ BACKUP_BOOT_SEC_IDX,
+ sector_sizes[i], false);
+ if (!ret) {
+ sect_size = sector_sizes[i];
+ goto restore;
+ }
}
+ exfat_err("backup boot region is also corrupted\n");
+ }
+
+ return ret;
+restore:
+ ret = restore_boot_region(exfat->blk_dev, sect_size);
+ if (ret) {
+ exfat_err("failed to restore boot region from backup\n");
+ free(*bs);
+ *bs = NULL;
}
return ret;
}
__le16 signature;
};
-/* Extended Boot Sector */
-struct exbs {
- __u8 zero[510];
- __le16 signature;
-};
-
-/* Extended Boot Record (8 sectors) */
-struct expbr {
- struct exbs eb[8];
-};
-
#define VOLUME_LABEL_MAX_LEN 11
#define ENTRY_NAME_MAX 15
#define EXFAT_GET_VOLUME_SERIAL 0x03
#define EXFAT_SET_VOLUME_SERIAL 0x04
+#define EXFAT_MAX_SECTOR_SIZE 4096
+
enum {
BOOT_SEC_IDX = 0,
EXBOOT_SEC_IDX,
int exfat_write_checksum_sector(struct exfat_blk_dev *bd,
unsigned int checksum, bool is_backup);
char *exfat_conv_volume_label(struct exfat_dentry *vol_entry);
-int exfat_show_volume_serial(struct exfat_blk_dev *bd,
- struct exfat_user_input *ui);
+int exfat_show_volume_serial(int fd);
int exfat_set_volume_serial(struct exfat_blk_dev *bd,
struct exfat_user_input *ui);
unsigned int exfat_clus_to_blk_dev_off(struct exfat_blk_dev *bd,
#ifndef _VERSION_H
-#define EXFAT_PROGS_VERSION "1.1.1"
+#define EXFAT_PROGS_VERSION "1.1.2"
#endif /* !_VERSION_H */
if (serial_mode) {
/* Mode to change or display volume serial */
if (flags == EXFAT_GET_VOLUME_SERIAL) {
- ret = exfat_show_volume_serial(&bd, &ui);
+ ret = exfat_show_volume_serial(bd.dev_fd);
} else if (flags == EXFAT_SET_VOLUME_SERIAL) {
ui.volume_serial = strtoul(argv[3], NULL, 0);
ret = exfat_set_volume_serial(&bd, &ui);
if (ioctl(fd, BLKSSZGET, &bd->sector_size) < 0)
bd->sector_size = DEFAULT_SECTOR_SIZE;
bd->sector_size_bits = sector_size_bits(bd->sector_size);
- bd->num_sectors = blk_dev_size / DEFAULT_SECTOR_SIZE;
+ bd->num_sectors = blk_dev_size / bd->sector_size;
bd->num_clusters = blk_dev_size / ui->cluster_size;
exfat_debug("Block device name : %s\n", ui->dev_name);
{
struct pbr *bs;
int nbytes;
- unsigned int cluster_size;
+ unsigned int cluster_size, sector_size;
off_t root_clu_off;
- bs = (struct pbr *)malloc(sizeof(struct pbr));
+ bs = (struct pbr *)malloc(EXFAT_MAX_SECTOR_SIZE);
if (!bs) {
exfat_err("failed to allocate memory\n");
return -ENOMEM;
}
- nbytes = exfat_read(bd->dev_fd, bs, sizeof(struct pbr), 0);
- if (nbytes != sizeof(struct pbr)) {
+ nbytes = exfat_read(bd->dev_fd, bs, EXFAT_MAX_SECTOR_SIZE, 0);
+ if (nbytes != EXFAT_MAX_SECTOR_SIZE) {
exfat_err("boot sector read failed: %d\n", errno);
free(bs);
return -1;
}
- cluster_size = (1 << bs->bsx.sect_per_clus_bits) * bd->sector_size;
- root_clu_off = le32_to_cpu(bs->bsx.clu_offset) * bd->sector_size +
- le32_to_cpu(bs->bsx.root_cluster - EXFAT_RESERVED_CLUSTERS)
- * cluster_size;
+ sector_size = 1 << bs->bsx.sect_size_bits;
+ cluster_size = (1 << bs->bsx.sect_per_clus_bits) * sector_size;
+ root_clu_off = le32_to_cpu(bs->bsx.clu_offset) * sector_size +
+ (le32_to_cpu(bs->bsx.root_cluster) - EXFAT_RESERVED_CLUSTERS) *
+ cluster_size;
free(bs);
return root_clu_off;
return ret;
}
-int exfat_show_volume_serial(struct exfat_blk_dev *bd,
- struct exfat_user_input *ui)
+int exfat_show_volume_serial(int fd)
{
struct pbr *ppbr;
int ret;
- ppbr = malloc(bd->sector_size);
+ ppbr = malloc(EXFAT_MAX_SECTOR_SIZE);
if (!ppbr) {
exfat_err("Cannot allocate pbr: out of memory\n");
return -1;
}
/* read main boot sector */
- ret = exfat_read_sector(bd, (char *)ppbr, BOOT_SEC_IDX);
+ ret = exfat_read(fd, (char *)ppbr, EXFAT_MAX_SECTOR_SIZE, 0);
if (ret < 0) {
exfat_err("main boot sector read failed\n");
ret = -1;
{
unsigned int checksum = 0;
int ret, sec_idx, backup_sec_idx = 0;
- int sector_size = bd->sector_size;
unsigned char *buf;
buf = malloc(bd->sector_size);
goto free_buf;
}
- if (sec_idx == BOOT_SEC_IDX) {
+ if (sec_idx == BOOT_SEC_IDX)
is_boot_sec = true;
- sector_size = sizeof(struct pbr);
- } else if (sec_idx >= EXBOOT_SEC_IDX && sec_idx < OEM_SEC_IDX)
- sector_size = sizeof(struct exbs);
- boot_calc_checksum(buf, sector_size, is_boot_sec,
+ boot_calc_checksum(buf, bd->sector_size, is_boot_sec,
&checksum);
}
int ret;
struct pbr *ppbr;
- ppbr = malloc(bd->sector_size);
+ ppbr = malloc(EXFAT_MAX_SECTOR_SIZE);
if (!ppbr) {
exfat_err("Cannot allocate pbr: out of memory\n");
return -1;
}
/* read main boot sector */
- ret = exfat_read_sector(bd, (char *)ppbr, BOOT_SEC_IDX);
+ ret = exfat_read(bd->dev_fd, (char *)ppbr, EXFAT_MAX_SECTOR_SIZE,
+ BOOT_SEC_IDX);
if (ret < 0) {
exfat_err("main boot sector read failed\n");
ret = -1;
goto free_ppbr;
}
+ bd->sector_size = 1 << ppbr->bsx.sect_size_bits;
ppbr->bsx.vol_serial = ui->volume_serial;
/* update main boot sector */
/* fs_version[0] : minor and fs_version[1] : major */
pbsx->fs_version[0] = 0;
pbsx->fs_version[1] = 1;
+ pbsx->phy_drv_no = 0x80;
memset(pbsx->reserved2, 0, 7);
memset(ppbr->boot_code, 0, 390);
if (is_backup)
sec_idx += BACKUP_BOOT_SEC_IDX;
- ppbr = malloc(sizeof(struct pbr));
+ ppbr = malloc(bd->sector_size);
if (!ppbr) {
exfat_err("Cannot allocate pbr: out of memory\n");
return -1;
}
- memset(ppbr, 0, sizeof(struct pbr));
+ memset(ppbr, 0, bd->sector_size);
exfat_setup_boot_sector(ppbr, bd, ui);
goto free_ppbr;
}
- boot_calc_checksum((unsigned char *)ppbr, sizeof(struct pbr),
+ boot_calc_checksum((unsigned char *)ppbr, bd->sector_size,
true, checksum);
free_ppbr:
static int exfat_write_extended_boot_sectors(struct exfat_blk_dev *bd,
unsigned int *checksum, bool is_backup)
{
- struct exbs eb;
+ char *peb;
+ __le16 *peb_signature;
+ int ret = 0;
int i;
unsigned int sec_idx = EXBOOT_SEC_IDX;
+ peb = malloc(bd->sector_size);
+ if (!peb)
+ return -1;
+
if (is_backup)
sec_idx += BACKUP_BOOT_SEC_IDX;
- memset(&eb, 0, sizeof(struct exbs));
- eb.signature = cpu_to_le16(PBR_SIGNATURE);
+ memset(peb, 0, bd->sector_size);
+ peb_signature = (__le16*) (peb + bd->sector_size - 2);
+ *peb_signature = cpu_to_le16(PBR_SIGNATURE);
for (i = 0; i < EXBOOT_SEC_NUM; i++) {
- if (exfat_write_sector(bd, &eb, sec_idx++)) {
+ if (exfat_write_sector(bd, peb, sec_idx++)) {
exfat_err("extended boot sector write failed\n");
- return -1;
+ ret = -1;
+ goto free_peb;
}
- boot_calc_checksum((unsigned char *) &eb, sizeof(struct exbs),
+ boot_calc_checksum((unsigned char *) peb, bd->sector_size,
false, checksum);
}
- return 0;
+free_peb:
+ free(peb);
+ return ret;
}
static int exfat_write_oem_sector(struct exfat_blk_dev *bd,
/* Mode to change or display volume serial */
if (flags == EXFAT_GET_VOLUME_SERIAL) {
- ret = exfat_show_volume_serial(&bd, &ui);
+ ret = exfat_show_volume_serial(bd.dev_fd);
goto close_fd_out;
} else if (flags == EXFAT_SET_VOLUME_SERIAL) {
ret = exfat_set_volume_serial(&bd, &ui);