1/* $NetBSD: v21.c,v 1.1 2022/01/22 08:09:40 pho Exp $ */
2
3/*
4 * Copyright (c) 2021 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote
16 *    products derived from this software without specific prior written
17 *    permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
20 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
25 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
33#if !defined(lint)
34__RCSID("$NetBSD: v21.c,v 1.1 2022/01/22 08:09:40 pho Exp $");
35#endif /* !lint */
36
37#include <err.h>
38#include <fuse_internal.h>
39
40/* Like FUSE 1.x, fuse_mount() is supposed to be called before
41 * fuse_new(). The argument "opts" is a comma-separated string of
42 * mount options. */
43int
44fuse_mount_v21(const char *mountpoint, const char *opts) {
45    struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
46    int nominal_fd = -1;
47
48    if (opts) {
49        if (fuse_opt_add_arg(&args, "-o") != 0)
50            goto free_args;
51
52        if (fuse_opt_add_arg(&args, opts) != 0)
53            goto free_args;
54    }
55
56    nominal_fd = fuse_mount_v25(mountpoint, &args);
57
58  free_args:
59    fuse_opt_free_args(&args);
60    return nominal_fd;
61}
62
63struct fuse *
64fuse_new_v21(int fd, const char *opts, const void *op,
65             int op_version, void *user_data) {
66    struct fuse_chan* chan;
67    struct fuse* fuse;
68    int rv;
69
70    chan = fuse_chan_peek(fd);
71    if (!chan) {
72        warnx("%s: invalid channel: %d", __func__, fd);
73        return NULL;
74    }
75
76    /* "opts" is another set of options to be interpreted by the FUSE
77     * library, as opposed to the ones passed to fuse_mount() which is
78     * handled by Linux kernel. We don't have such a distinction, so
79     * insert them at argv[1] (not at the end of argv, because there
80     * may be non-options there). */
81    if (opts) {
82        if (fuse_opt_insert_arg(fuse_chan_args(chan), 1, "-o") != 0) {
83            fuse_chan_destroy(chan);
84            return NULL;
85        }
86        if (fuse_opt_insert_arg(fuse_chan_args(chan), 2, opts) != 0) {
87            fuse_chan_destroy(chan);
88            return NULL;
89        }
90    }
91
92    fuse = __fuse_new(fuse_chan_args(chan), op, op_version, user_data);
93    if (!fuse) {
94        fuse_chan_destroy(chan);
95        return NULL;
96    }
97    fuse_chan_set_fuse(chan, fuse);
98
99    /* Now we can finally mount it. Hope it's not too late. */
100    rv = fuse_mount_v30(fuse, fuse_chan_mountpoint(chan));
101    if (rv != 0) {
102        fuse_destroy_v30(fuse);
103        fuse_chan_destroy(chan);
104        return NULL;
105    }
106
107    return fuse;
108}
109