+2005-07-21 Miklos Szeredi <miklos@szeredi.hu>
+
+ * Don't change mtime/ctime/atime to local time on read/write.
+ Bug reported by Ben Grimm
+
+ * Install fuse_common.h and fuse_lowlevel.h. Report by Christian
+ Magnusson
+
+ * fusermount: use getopt_long() for option parsing. It allows the
+ use of '--' to stop argument scanning, so fusermount can now
+ operate on directories whose names begin with a '-'. Patch by
+ Adam Connell
+
2005-07-15 Miklos Szeredi <miklos@szeredi.hu>
* fusermount: add '-v', '--version' and '--help' options
stbuf->st_mode = S_IFDIR | 0755;
stbuf->st_nlink = 2;
break;
-
+
case 2:
stbuf->st_mode = S_IFREG | 0444;
stbuf->st_nlink = 1;
stbuf->st_size = strlen(hello_str);
break;
-
+
default:
return -1;
}
e.attr_timeout = 1.0;
e.entry_timeout = 1.0;
hello_stat(e.ino, &e.attr);
-
+
fuse_reply_entry(req, &e);
}
}
static int reply_buf_limited(fuse_req_t req, const char *buf, size_t bufsize,
off_t off, size_t maxsize)
{
-
if (off < bufsize)
return fuse_reply_buf(req, buf + off, min(bufsize - off, maxsize));
else
fuse_reply_err(req, ENOTDIR);
else {
struct dirbuf b;
-
+
memset(&b, 0, sizeof(b));
dirbuf_add(&b, ".", 1);
dirbuf_add(&b, "..", 1);
## Process this file with automake to produce Makefile.in
fuseincludedir=$(includedir)/fuse
-fuseinclude_HEADERS = fuse.h fuse_compat.h
+fuseinclude_HEADERS = fuse.h fuse_compat.h fuse_common.h fuse_lowlevel.h
include_HEADERS = old/fuse.h
noinst_HEADERS = fuse_kernel.h
* is permitted for the given flags. Optionally open may also
* return an arbitary filehandle in the fuse_file_info structure,
* which will be passed to all file operations.
- *
+ *
* Changed in version 2.2
*/
int (*open) (const char *, struct fuse_file_info *);
* not possible to determine if a flush is final, so each flush
* should be treated equally. Multiple write-flush sequences are
* relatively rare, so this shouldn't be a problem.
- *
+ *
* Changed in version 2.2
*/
int (*flush) (const char *, struct fuse_file_info *);
* passes non-zero offset to the filler function. When the buffer
* is full (or an error happens) the filler function will return
* '1'.
- *
+ *
* Introduced in version 2.3
*/
int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t,
struct fuse_file_info *);
- /** Release directory
+ /** Release directory
*
* Introduced in version 2.3
*/
* The return value will passed in the private_data field of
* fuse_context to all file operations and as a parameter to the
* destroy() method.
- *
+ *
* Introduced in version 2.3
*/
void *(*init) (void);
* Clean up filesystem
*
* Called on filesystem exit.
- *
+ *
* Introduced in version 2.3
*/
void (*destroy) (void *);
/**
* Obsolete, doesn't do anything
- *
+ *
* @return -EINVAL
*/
int fuse_invalidate(struct fuse *f, const char *path);
fuse_put_request(fc, req);
if (!err)
SetPageUptodate(page);
+ if (!(inode->i_sb->s_flags & MS_NOATIME))
+ fuse_invalidate_attr(inode);
out:
unlock_page(page);
return err;
SetPageUptodate(page);
unlock_page(page);
}
+ if (!(inode->i_sb->s_flags & MS_NOATIME))
+ fuse_invalidate_attr(inode);
return req->out.h.error;
}
clear_page_dirty(page);
SetPageUptodate(page);
}
- } else if (err == -EINTR || err == -EIO)
- fuse_invalidate_attr(inode);
+ }
+ fuse_invalidate_attr(inode);
return err;
}
if (write && pos > i_size_read(inode))
i_size_write(inode, pos);
*ppos = pos;
- } else if (write && (res == -EINTR || res == -EIO))
+ }
+ if (write || !(inode->i_sb->s_flags & MS_NOATIME))
fuse_invalidate_attr(inode);
return res;
static struct file_operations fuse_file_operations = {
.llseek = generic_file_llseek,
#ifdef KERNEL_2_6
- .read = generic_file_read,
+ .read = generic_file_read,
#else
.read = fuse_file_read,
#endif
return NULL;
if ((inode->i_state & I_NEW)) {
+ inode->i_flags |= S_NOATIME|S_NOCMTIME;
inode->i_generation = generation;
inode->i_data.backing_dev_info = &fc->bdi;
fuse_init_inode(inode, attr);
return 0;
}
}
-
+
if (!d->fd_present || !d->rootmode_present ||
!d->user_id_present || !d->group_id_present)
return 0;
int err)
{
if (!err) {
- if (fuse_reply_entry(req, e) == -ENOENT)
+ if (fuse_reply_entry(req, e) == -ENOENT)
forget_node(req_fuse(req), e->ino, 1);
} else
reply_err(req, err);
struct fuse_file_info *llfi)
{
struct fuse *f = req_fuse_prepare(req);
- struct fuse_file_info fi;
+ struct fuse_file_info fi;
struct fuse_dirhandle *dh = get_dirhandle(llfi, &fi);
if (f->op.releasedir) {
char *path;
if (fuse_ll_is_lib_option(opt)) {
size_t optlen = strlen(opt);
if (strcmp(opt, "debug") == 0)
- f->flags |= FUSE_DEBUG;
+ f->flags |= FUSE_DEBUG;
memmove(d, opt, optlen);
d += optlen;
*d++ = ',';
memset(&arg, 0, sizeof(arg));
arg.fh = f->fh;
-
+
return send_reply_req(req, &arg, sizeof(arg));
}
memset(&arg, 0, sizeof(arg));
arg.size = count;
-
+
return send_reply_req(req, &arg, sizeof(arg));
}
memset(&arg, 0, sizeof(arg));
convert_statfs(statfs, &arg.st);
-
+
return send_reply_req(req, &arg, sizeof(arg));
}
memset(&arg, 0, sizeof(arg));
arg.size = count;
-
+
return send_reply_req(req, &arg, sizeof(arg));
}
struct fuse_open_in *arg)
{
struct fuse_file_info fi;
-
+
memset(&fi, 0, sizeof(fi));
fi.flags = arg->flags;
fprintf(stderr, "fuse: failed to allocate request\n");
goto out;
}
-
+
req->f = f;
req->unique = in->unique;
req->ctx.uid = in->uid;
static struct fuse_context *mt_getcontext(void)
{
struct fuse_context *ctx;
-
+
ctx = (struct fuse_context *) pthread_getspecific(context_key);
if (ctx == NULL) {
ctx = (struct fuse_context *) malloc(sizeof(struct fuse_context));
}
static struct fuse *fuse_setup_common(int argc, char *argv[],
-
const struct fuse_operations *op,
size_t op_size,
char **mountpoint,
const char *mountprog = FUSERMOUNT_PROG;
char umount_cmd[1024];
- snprintf(umount_cmd, sizeof(umount_cmd) - 1, "%s -u -q -z %s", mountprog,
- mountpoint);
+ snprintf(umount_cmd, sizeof(umount_cmd) - 1, "%s -u -q -z -- %s",
+ mountprog, mountpoint);
umount_cmd[sizeof(umount_cmd) - 1] = '\0';
system(umount_cmd);
if(pid == 0) {
char env[10];
- const char *argv[] = {mountprog, opts ? "-o" : mountpoint, opts,
- mountpoint, NULL};
+ const char *argv[32];
+ int a = 0;
+
+ argv[a++] = mountprog;
+ if (opts) {
+ argv[a++] = "-o";
+ argv[a++] = opts;
+ }
+ argv[a++] = "--";
+ argv[a++] = mountpoint;
+ argv[a++] = NULL;
close(fds[1]);
fcntl(fds[0], F_SETFD, 0);
static void start_test(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
-
+
static void test_error(const char *func, const char *msg, ...)
{
va_list ap;
{
int res;
int fd;
-
+
unlink(path);
fd = creat(path, 0644);
if (fd == -1) {
res = check_mode(path, 0755);
if (res == -1)
return -1;
-
+
for (i = 0; dir_files[i]; i++) {
char fpath[1024];
sprintf(fpath, "%s/%s", path, dir_files[i]);
res = create_file(testfile, data, datalen);
if (res == -1)
return -1;
-
+
res = truncate(testfile, len);
if (res == -1) {
PERROR("truncate");
res = check_size(testfile, len);
if (res == -1)
return -1;
-
+
if (len > 0) {
if (len <= datalen) {
res = check_data(testfile, data, 0, len);
res = create_file(testfile, data, datalen);
if (res == -1)
return -1;
-
+
unlink(testfile2);
res = symlink(testfile, testfile2);
if (res == -1) {
res = create_file(testfile, data, datalen);
if (res == -1)
return -1;
-
+
unlink(testfile2);
res = rename(testfile, testfile2);
if (res == -1) {
res = create_dir(testdir, testdir_files);
if (res == -1)
return -1;
-
+
rmdir(testdir2);
res = rename(testdir, testdir2);
if (res == -1) {
#include <string.h>
#include <ctype.h>
#include <unistd.h>
+#include <getopt.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
progname, origmnt, strerror(errno));
return -1;
}
-
+
if ((stbuf->st_mode & S_ISVTX) && stbuf->st_uid != getuid()) {
fprintf(stderr, "%s: mountpoint %s not owned by user\n",
progname, origmnt);
return -1;
}
-
+
res = access(mnt, W_OK);
if (res == -1) {
fprintf(stderr, "%s: user has no write access to mountpoint %s\n",
int main(int argc, char *argv[])
{
- int a;
+ int ch;
int fd;
int res;
char *origmnt;
char *mnt;
- int unmount = 0;
- int lazy = 0;
+ static int unmount = 0;
+ static int lazy = 0;
+ static int quiet = 0;
char *commfd;
- int quiet = 0;
int cfd;
const char *opts = "";
- progname = argv[0];
-
- for (a = 1; a < argc; a++) {
- if (argv[a][0] != '-')
- break;
+ static const struct option long_opts[] = {
+ {"unmount", no_argument, NULL, 'u'},
+ {"lazy", no_argument, NULL, 'z'},
+ {"quiet", no_argument, NULL, 'q'},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'v'},
+ {0, 0, 0, 0}};
+
+ progname = strdup(argv[0]);
+ if (progname == NULL) {
+ fprintf(stderr, "%s: failed to allocate memory\n", argv[0]);
+ exit(1);
+ }
- switch (argv[a][1]) {
+ while ((ch = getopt_long(argc, argv, "hvo:uzq", long_opts, NULL)) != -1) {
+ switch (ch) {
case 'h':
usage();
break;
break;
case 'o':
- a++;
- if (a == argc) {
- fprintf(stderr, "%s: missing argument to -o\n", progname);
- exit(1);
- }
- opts = argv[a];
+ opts = optarg;
break;
case 'u':
quiet = 1;
break;
- case '-':
- if (strcmp(&argv[a][2], "help") == 0)
- usage();
- else if (strcmp(&argv[a][2], "version") == 0)
- show_version();
-
- /* fall through */
-
default:
- fprintf(stderr, "%s: unknown option '%s'\n", progname, argv[a]);
- fprintf(stderr, "Try `%s -h' for more information\n", progname);
exit(1);
}
}
exit(1);
}
- if (a == argc) {
+ if (optind >= argc) {
fprintf(stderr, "%s: missing mountpoint argument\n", progname);
exit(1);
}
- origmnt = argv[a++];
+ origmnt = argv[optind];
drop_privs();
mnt = resolve_path(origmnt);