main.c (01.09.09)
FUSE-based exFAT implementation. Requires FUSE 2.6 or later.
- Copyright (C) 2009, 2010 Andrew Nayenko
+ Copyright (C) 2010-2012 Andrew Nayenko
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#define FUSE_USE_VERSION 26
#include <fuse.h>
#include <errno.h>
#include <fcntl.h>
#error FUSE 2.6 or later is required
#endif
-const char* default_options = "allow_other,blkdev";
+const char* default_options = "ro_fallback,allow_other,blkdev";
struct exfat ef;
off_t offset, struct fuse_file_info* fi)
{
exfat_debug("[fuse_exfat_read] %s (%zu bytes)", path, size);
- return exfat_read(&ef, get_node(fi), buffer, size, offset);
+ return exfat_generic_pread(&ef, get_node(fi), buffer, size, offset);
}
static int fuse_exfat_write(const char* path, const char* buffer, size_t size,
off_t offset, struct fuse_file_info* fi)
{
exfat_debug("[fuse_exfat_write] %s (%zu bytes)", path, size);
- return exfat_write(&ef, get_node(fi), buffer, size, offset);
+ return exfat_generic_pwrite(&ef, get_node(fi), buffer, size, offset);
}
static int fuse_exfat_unlink(const char* path)
return 0;
}
+#ifdef __APPLE__
+static int fuse_exfat_chmod(const char* path, mode_t mode)
+{
+ exfat_debug("[fuse_exfat_chmod] %s 0%ho", path, mode);
+ /* make OS X utilities happy */
+ return 0;
+}
+#endif
+
static int fuse_exfat_statfs(const char* path, struct statvfs* sfs)
{
sfs->f_bsize = CLUSTER_SIZE(*ef.sb);
sfs->f_frsize = CLUSTER_SIZE(*ef.sb);
- sfs->f_blocks = le64_to_cpu(ef.sb->block_count) >> ef.sb->bpc_bits;
+ sfs->f_blocks = le64_to_cpu(ef.sb->sector_count) >> ef.sb->spc_bits;
sfs->f_bavail = exfat_count_free_clusters(&ef);
sfs->f_bfree = sfs->f_bavail;
sfs->f_namemax = EXFAT_NAME_MAX;
b) no such thing as inode;
So here we assume that inode = cluster.
*/
- sfs->f_files = (sfs->f_blocks - sfs->f_bfree) >> ef.sb->bpc_bits;
- sfs->f_favail = sfs->f_bfree >> ef.sb->bpc_bits;
+ sfs->f_files = (sfs->f_blocks - sfs->f_bfree) >> ef.sb->spc_bits;
+ sfs->f_favail = sfs->f_bfree >> ef.sb->spc_bits;
sfs->f_ffree = sfs->f_bavail;
return 0;
static void usage(const char* prog)
{
- fprintf(stderr, "Usage: %s [-d] [-o options] <device> <dir>\n", prog);
+ fprintf(stderr, "Usage: %s [-d] [-o options] [-v] <device> <dir>\n", prog);
exit(1);
}
.mkdir = fuse_exfat_mkdir,
.rename = fuse_exfat_rename,
.utimens = fuse_exfat_utimens,
+#ifdef __APPLE__
+ .chmod = fuse_exfat_chmod,
+#endif
.statfs = fuse_exfat_statfs,
.destroy = fuse_exfat_destroy,
};
}
else if (strcmp(*pp, "-d") == 0)
debug = 1;
+ else if (strcmp(*pp, "-v") == 0)
+ {
+ free(mount_options);
+ puts("Copyright (C) 2010-2012 Andrew Nayenko");
+ return 0;
+ }
else if (spec == NULL)
spec = *pp;
else if (mount_point == NULL)
return 1;
}
+ if (ef.ro == -1) /* read-only fallback was used */
+ {
+ mount_options = add_option(mount_options, "ro", NULL);
+ if (mount_options == NULL)
+ {
+ exfat_unmount(&ef);
+ return 1;
+ }
+ }
+
mount_options = add_fuse_options(mount_options, spec);
if (mount_options == NULL)
{
}
/* exit session on HUP, TERM and INT signals and ignore PIPE signal */
- if (fuse_set_signal_handlers(fuse_get_session(fh)))
+ if (fuse_set_signal_handlers(fuse_get_session(fh)) != 0)
{
fuse_unmount(mount_point, fc);
fuse_destroy(fh);
exfat_unmount(&ef);
+ exfat_error("failed to set signal handlers");
return 1;
}
- /* go to background unless "-d" option is passed */
- fuse_daemonize(debug);
-
- /* FUSE main loop */
- fuse_loop(fh);
+ /* go to background (unless "-d" option is passed) and run FUSE
+ main loop */
+ if (fuse_daemonize(debug) == 0)
+ {
+ if (fuse_loop(fh) != 0)
+ exfat_error("FUSE loop failure");
+ }
+ else
+ exfat_error("failed to daemonize");
- /* it's quite illogical but fuse_unmount() must be called BEFORE
- fuse_destroy() */
+ fuse_remove_signal_handlers(fuse_get_session(fh));
+ /* note that fuse_unmount() must be called BEFORE fuse_destroy() */
fuse_unmount(mount_point, fc);
fuse_destroy(fh);
return 0;