X-Git-Url: https://git.sven.stormbind.net/?p=sven%2Ffuse-exfat.git;a=blobdiff_plain;f=fuse%2Fmain.c;h=15273473b7ce2ead25f5c972e55b5c2a713b263e;hp=643df3f7e7557bf51282a9fc566a6c3b281de901;hb=c1c45856c432c68749276ecbeff56c88f85bcd3e;hpb=31c7740425f6fc11cc1f4c4316c659c566d94036 diff --git a/fuse/main.c b/fuse/main.c index 643df3f..1527347 100644 --- a/fuse/main.c +++ b/fuse/main.c @@ -2,7 +2,7 @@ main.c (01.09.09) FUSE-based exFAT implementation. Requires FUSE 2.6 or later. - Copyright (C) 2010-2012 Andrew Nayenko + Copyright (C) 2010-2013 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 @@ -38,7 +38,8 @@ #error FUSE 2.6 or later is required #endif -const char* default_options = "ro_fallback,allow_other,blkdev"; +const char* default_options = "ro_fallback,allow_other,blkdev,big_writes," + "defer_permissions"; struct exfat ef; @@ -57,7 +58,7 @@ static int fuse_exfat_getattr(const char* path, struct stat* stbuf) struct exfat_node* node; int rc; - exfat_debug("[fuse_exfat_getattr] %s", path); + exfat_debug("[%s] %s", __func__, path); rc = exfat_lookup(&ef, &node, path); if (rc != 0) @@ -73,7 +74,7 @@ static int fuse_exfat_truncate(const char* path, off_t size) struct exfat_node* node; int rc; - exfat_debug("[fuse_exfat_truncate] %s, %"PRIu64, path, (uint64_t) size); + exfat_debug("[%s] %s, %"PRId64, __func__, path, size); rc = exfat_lookup(&ef, &node, path); if (rc != 0) @@ -93,7 +94,7 @@ static int fuse_exfat_readdir(const char* path, void* buffer, int rc; char name[EXFAT_NAME_MAX + 1]; - exfat_debug("[fuse_exfat_readdir] %s", path); + exfat_debug("[%s] %s", __func__, path); rc = exfat_lookup(&ef, &parent, path); if (rc != 0) @@ -118,9 +119,9 @@ static int fuse_exfat_readdir(const char* path, void* buffer, while ((node = exfat_readdir(&ef, &it))) { exfat_get_name(node, name, EXFAT_NAME_MAX); - exfat_debug("[fuse_exfat_readdir] %s: %s, %"PRIu64" bytes, cluster %u", + exfat_debug("[%s] %s: %s, %"PRId64" bytes, cluster 0x%x", __func__, name, IS_CONTIGUOUS(*node) ? "contiguous" : "fragmented", - (uint64_t) node->size, node->start_cluster); + node->size, node->start_cluster); filler(buffer, name, NULL, 0); exfat_put_node(&ef, node); } @@ -134,7 +135,7 @@ static int fuse_exfat_open(const char* path, struct fuse_file_info* fi) struct exfat_node* node; int rc; - exfat_debug("[fuse_exfat_open] %s", path); + exfat_debug("[%s] %s", __func__, path); rc = exfat_lookup(&ef, &node, path); if (rc != 0) @@ -146,6 +147,7 @@ static int fuse_exfat_open(const char* path, struct fuse_file_info* fi) static int fuse_exfat_release(const char* path, struct fuse_file_info* fi) { + exfat_debug("[%s] %s", __func__, path); exfat_put_node(&ef, get_node(fi)); return 0; } @@ -153,15 +155,19 @@ static int fuse_exfat_release(const char* path, struct fuse_file_info* fi) static int fuse_exfat_read(const char* path, char* buffer, size_t size, off_t offset, struct fuse_file_info* fi) { - exfat_debug("[fuse_exfat_read] %s (%zu bytes)", path, size); - return exfat_generic_pread(&ef, get_node(fi), buffer, size, offset); + exfat_debug("[%s] %s (%zu bytes)", __func__, path, size); + if (exfat_generic_pread(&ef, get_node(fi), buffer, size, offset) != size) + return EOF; + return size; } 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_generic_pwrite(&ef, get_node(fi), buffer, size, offset); + exfat_debug("[%s] %s (%zu bytes)", __func__, path, size); + if (exfat_generic_pwrite(&ef, get_node(fi), buffer, size, offset) != size) + return EOF; + return size; } static int fuse_exfat_unlink(const char* path) @@ -169,7 +175,7 @@ static int fuse_exfat_unlink(const char* path) struct exfat_node* node; int rc; - exfat_debug("[fuse_exfat_unlink] %s", path); + exfat_debug("[%s] %s", __func__, path); rc = exfat_lookup(&ef, &node, path); if (rc != 0) @@ -185,7 +191,7 @@ static int fuse_exfat_rmdir(const char* path) struct exfat_node* node; int rc; - exfat_debug("[fuse_exfat_rmdir] %s", path); + exfat_debug("[%s] %s", __func__, path); rc = exfat_lookup(&ef, &node, path); if (rc != 0) @@ -198,19 +204,19 @@ static int fuse_exfat_rmdir(const char* path) static int fuse_exfat_mknod(const char* path, mode_t mode, dev_t dev) { - exfat_debug("[fuse_exfat_mknod] %s", path); + exfat_debug("[%s] %s 0%ho", __func__, path, mode); return exfat_mknod(&ef, path); } static int fuse_exfat_mkdir(const char* path, mode_t mode) { - exfat_debug("[fuse_exfat_mkdir] %s", path); + exfat_debug("[%s] %s 0%ho", __func__, path, mode); return exfat_mkdir(&ef, path); } static int fuse_exfat_rename(const char* old_path, const char* new_path) { - exfat_debug("[fuse_exfat_rename] %s => %s", old_path, new_path); + exfat_debug("[%s] %s => %s", __func__, old_path, new_path); return exfat_rename(&ef, old_path, new_path); } @@ -219,7 +225,7 @@ static int fuse_exfat_utimens(const char* path, const struct timespec tv[2]) struct exfat_node* node; int rc; - exfat_debug("[fuse_exfat_utimens] %s", path); + exfat_debug("[%s] %s", __func__, path); rc = exfat_lookup(&ef, &node, path); if (rc != 0) @@ -230,8 +236,19 @@ static int fuse_exfat_utimens(const char* path, const struct timespec tv[2]) return 0; } +#ifdef __APPLE__ +static int fuse_exfat_chmod(const char* path, mode_t mode) +{ + exfat_debug("[%s] %s 0%ho", __func__, path, mode); + /* make OS X utilities happy */ + return 0; +} +#endif + static int fuse_exfat_statfs(const char* path, struct statvfs* sfs) { + exfat_debug("[%s]", __func__); + sfs->f_bsize = CLUSTER_SIZE(*ef.sb); sfs->f_frsize = CLUSTER_SIZE(*ef.sb); sfs->f_blocks = le64_to_cpu(ef.sb->sector_count) >> ef.sb->spc_bits; @@ -252,8 +269,18 @@ static int fuse_exfat_statfs(const char* path, struct statvfs* sfs) return 0; } +static void* fuse_exfat_init(struct fuse_conn_info* fci) +{ + exfat_debug("[%s]", __func__); +#ifdef FUSE_CAP_BIG_WRITES + fci->want |= FUSE_CAP_BIG_WRITES; +#endif + return NULL; +} + static void fuse_exfat_destroy(void* unused) { + exfat_debug("[%s]", __func__); exfat_unmount(&ef); } @@ -278,7 +305,11 @@ static struct fuse_operations fuse_exfat_ops = .mkdir = fuse_exfat_mkdir, .rename = fuse_exfat_rename, .utimens = fuse_exfat_utimens, +#ifdef __APPLE__ + .chmod = fuse_exfat_chmod, +#endif .statfs = fuse_exfat_statfs, + .init = fuse_exfat_init, .destroy = fuse_exfat_destroy, }; @@ -309,15 +340,17 @@ static char* add_option(char* options, const char* name, const char* value) static char* add_fsname_option(char* options, const char* spec) { - char spec_abs[PATH_MAX]; + char* spec_abs = realpath(spec, NULL); - if (realpath(spec, spec_abs) == NULL) + if (spec_abs == NULL) { free(options); exfat_error("failed to get absolute path for `%s'", spec); return NULL; } - return add_option(options, "fsname", spec_abs); + options = add_option(options, "fsname", spec_abs); + free(spec_abs); + return options; } static char* add_user_option(char* options) @@ -402,7 +435,7 @@ int main(int argc, char* argv[]) else if (strcmp(*pp, "-v") == 0) { free(mount_options); - puts("Copyright (C) 2010-2012 Andrew Nayenko"); + puts("Copyright (C) 2010-2013 Andrew Nayenko"); return 0; } else if (spec == NULL) @@ -427,7 +460,7 @@ int main(int argc, char* argv[]) 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) @@ -486,22 +519,27 @@ int main(int argc, char* argv[]) } /* 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;