struct exfat_dev* dev;
struct exfat_super_block sb;
- dev = exfat_open(spec, 1);
+ dev = exfat_open(spec, EXFAT_MODE_RO);
if (dev == NULL)
return 1;
return 1;
}
- if (ef.ro_fallback)
+ if (ef.ro == -1) /* read-only fallback was used */
{
mount_options = add_option(mount_options, "ro", NULL);
if (mount_options == NULL)
le16_t name[EXFAT_NAME_MAX + 1];
};
+enum exfat_mode
+{
+ EXFAT_MODE_RO,
+ EXFAT_MODE_RW,
+ EXFAT_MODE_ANY,
+};
+
struct exfat_dev;
struct exfat
uid_t uid;
gid_t gid;
int ro;
- int ro_fallback;
int noatime;
};
void exfat_debug(const char* format, ...)
__attribute__((format(printf, 1, 2)));
-struct exfat_dev* exfat_open(const char* spec, int ro);
+struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode);
int exfat_close(struct exfat_dev* dev);
int exfat_fsync(struct exfat_dev* dev);
+enum exfat_mode exfat_mode(const struct exfat_dev* dev);
off_t exfat_seek(struct exfat_dev* dev, off_t offset, int whence);
ssize_t exfat_read(struct exfat_dev* dev, void* buffer, size_t size);
ssize_t exfat_write(struct exfat_dev* dev, const void* buffer, size_t size);
struct exfat_dev
{
int fd;
+ enum exfat_mode mode;
#ifdef USE_UBLIO
off_t pos;
ublio_filehandle_t ufh;
#endif
};
-struct exfat_dev* exfat_open(const char* spec, int ro)
+struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode)
{
struct exfat_dev* dev;
struct stat stbuf;
return NULL;
}
- dev->fd = open(spec, ro ? O_RDONLY : O_RDWR);
- if (dev->fd < 0)
+ switch (mode)
{
+ case EXFAT_MODE_RO:
+ dev->fd = open(spec, O_RDONLY);
+ if (dev->fd == -1)
+ {
+ free(dev);
+ exfat_error("failed to open `%s' in read-only mode", spec);
+ return NULL;
+ }
+ dev->mode = EXFAT_MODE_RO;
+ break;
+ case EXFAT_MODE_RW:
+ dev->fd = open(spec, O_RDWR);
+ if (dev->fd == -1)
+ {
+ free(dev);
+ exfat_error("failed to open `%s' in read-write mode", spec);
+ return NULL;
+ }
+ dev->mode = EXFAT_MODE_RW;
+ break;
+ case EXFAT_MODE_ANY:
+ dev->fd = open(spec, O_RDWR);
+ if (dev->fd != -1)
+ {
+ dev->mode = EXFAT_MODE_RW;
+ break;
+ }
+ dev->fd = open(spec, O_RDONLY);
+ if (dev->fd != -1)
+ {
+ dev->mode = EXFAT_MODE_RO;
+ exfat_warn("`%s' is write-protected, mounting read-only", spec);
+ break;
+ }
free(dev);
- exfat_error("failed to open `%s' in read-%s mode", spec,
- ro ? "only" : "write");
+ exfat_error("failed to open `%s'", spec);
return NULL;
}
+
if (fstat(dev->fd, &stbuf) != 0)
{
close(dev->fd);
return 0;
}
+enum exfat_mode exfat_mode(const struct exfat_dev* dev)
+{
+ return dev->mode;
+}
+
off_t exfat_seek(struct exfat_dev* dev, off_t offset, int whence)
{
#ifdef USE_UBLIO
ef->uid = get_int_option(options, "uid", 10, geteuid());
ef->gid = get_int_option(options, "gid", 10, getegid());
- ef->ro = match_option(options, "ro");
ef->noatime = match_option(options, "noatime");
}
int exfat_mount(struct exfat* ef, const char* spec, const char* options)
{
int rc;
+ enum exfat_mode mode;
exfat_tzset();
memset(ef, 0, sizeof(struct exfat));
parse_options(ef, options);
- ef->dev = exfat_open(spec, ef->ro);
+ if (match_option(options, "ro"))
+ mode = EXFAT_MODE_RO;
+ else if (match_option(options, "ro_fallback"))
+ mode = EXFAT_MODE_ANY;
+ else
+ mode = EXFAT_MODE_RW;
+ ef->dev = exfat_open(spec, mode);
if (ef->dev == NULL)
+ return -EIO;
+ if (exfat_mode(ef->dev) == EXFAT_MODE_RO)
{
- if (ef->ro || !match_option(options, "ro_fallback"))
- return -EIO;
- ef->dev = exfat_open(spec, 1);
- if (ef->dev == NULL)
- return -EIO;
- exfat_warn("device is write-protected, mounting read-only");
- ef->ro_fallback = ef->ro = 1;
+ if (mode == EXFAT_MODE_ANY)
+ ef->ro = -1;
+ else
+ ef->ro = 1;
}
ef->sb = malloc(sizeof(struct exfat_super_block));
if (spec == NULL)
usage(argv[0]);
- dev = exfat_open(spec, 0);
+ dev = exfat_open(spec, EXFAT_MODE_RW);
if (dev == NULL)
return 1;
if (setup(dev, 9, spc_bits, volume_label, volume_serial,