16881f68fSopenharmony_ci/*
26881f68fSopenharmony_ci  CUSE: Character device in Userspace
36881f68fSopenharmony_ci  Copyright (C) 2008       SUSE Linux Products GmbH
46881f68fSopenharmony_ci  Copyright (C) 2008       Tejun Heo <teheo@suse.de>
56881f68fSopenharmony_ci
66881f68fSopenharmony_ci  This program can be distributed under the terms of the GNU LGPLv2.
76881f68fSopenharmony_ci  See the file COPYING.LIB.
86881f68fSopenharmony_ci*/
96881f68fSopenharmony_ci
106881f68fSopenharmony_ci#include "fuse_config.h"
116881f68fSopenharmony_ci#include "cuse_lowlevel.h"
126881f68fSopenharmony_ci#include "fuse_kernel.h"
136881f68fSopenharmony_ci#include "fuse_i.h"
146881f68fSopenharmony_ci#include "fuse_opt.h"
156881f68fSopenharmony_ci
166881f68fSopenharmony_ci#include <stdio.h>
176881f68fSopenharmony_ci#include <string.h>
186881f68fSopenharmony_ci#include <stdlib.h>
196881f68fSopenharmony_ci#include <stddef.h>
206881f68fSopenharmony_ci#include <errno.h>
216881f68fSopenharmony_ci#include <unistd.h>
226881f68fSopenharmony_ci
236881f68fSopenharmony_cistruct cuse_data {
246881f68fSopenharmony_ci	struct cuse_lowlevel_ops	clop;
256881f68fSopenharmony_ci	unsigned			max_read;
266881f68fSopenharmony_ci	unsigned			dev_major;
276881f68fSopenharmony_ci	unsigned			dev_minor;
286881f68fSopenharmony_ci	unsigned			flags;
296881f68fSopenharmony_ci	unsigned			dev_info_len;
306881f68fSopenharmony_ci	char				dev_info[];
316881f68fSopenharmony_ci};
326881f68fSopenharmony_ci
336881f68fSopenharmony_cistatic struct cuse_lowlevel_ops *req_clop(fuse_req_t req)
346881f68fSopenharmony_ci{
356881f68fSopenharmony_ci	return &req->se->cuse_data->clop;
366881f68fSopenharmony_ci}
376881f68fSopenharmony_ci
386881f68fSopenharmony_cistatic void cuse_fll_open(fuse_req_t req, fuse_ino_t ino,
396881f68fSopenharmony_ci			  struct fuse_file_info *fi)
406881f68fSopenharmony_ci{
416881f68fSopenharmony_ci	(void)ino;
426881f68fSopenharmony_ci	req_clop(req)->open(req, fi);
436881f68fSopenharmony_ci}
446881f68fSopenharmony_ci
456881f68fSopenharmony_cistatic void cuse_fll_read(fuse_req_t req, fuse_ino_t ino, size_t size,
466881f68fSopenharmony_ci			  off_t off, struct fuse_file_info *fi)
476881f68fSopenharmony_ci{
486881f68fSopenharmony_ci	(void)ino;
496881f68fSopenharmony_ci	req_clop(req)->read(req, size, off, fi);
506881f68fSopenharmony_ci}
516881f68fSopenharmony_ci
526881f68fSopenharmony_cistatic void cuse_fll_write(fuse_req_t req, fuse_ino_t ino, const char *buf,
536881f68fSopenharmony_ci			   size_t size, off_t off, struct fuse_file_info *fi)
546881f68fSopenharmony_ci{
556881f68fSopenharmony_ci	(void)ino;
566881f68fSopenharmony_ci	req_clop(req)->write(req, buf, size, off, fi);
576881f68fSopenharmony_ci}
586881f68fSopenharmony_ci
596881f68fSopenharmony_cistatic void cuse_fll_flush(fuse_req_t req, fuse_ino_t ino,
606881f68fSopenharmony_ci			   struct fuse_file_info *fi)
616881f68fSopenharmony_ci{
626881f68fSopenharmony_ci	(void)ino;
636881f68fSopenharmony_ci	req_clop(req)->flush(req, fi);
646881f68fSopenharmony_ci}
656881f68fSopenharmony_ci
666881f68fSopenharmony_cistatic void cuse_fll_release(fuse_req_t req, fuse_ino_t ino,
676881f68fSopenharmony_ci			     struct fuse_file_info *fi)
686881f68fSopenharmony_ci{
696881f68fSopenharmony_ci	(void)ino;
706881f68fSopenharmony_ci	req_clop(req)->release(req, fi);
716881f68fSopenharmony_ci}
726881f68fSopenharmony_ci
736881f68fSopenharmony_cistatic void cuse_fll_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
746881f68fSopenharmony_ci			   struct fuse_file_info *fi)
756881f68fSopenharmony_ci{
766881f68fSopenharmony_ci	(void)ino;
776881f68fSopenharmony_ci	req_clop(req)->fsync(req, datasync, fi);
786881f68fSopenharmony_ci}
796881f68fSopenharmony_ci
806881f68fSopenharmony_cistatic void cuse_fll_ioctl(fuse_req_t req, fuse_ino_t ino, unsigned int cmd, void *arg,
816881f68fSopenharmony_ci			   struct fuse_file_info *fi, unsigned int flags,
826881f68fSopenharmony_ci			   const void *in_buf, size_t in_bufsz, size_t out_bufsz)
836881f68fSopenharmony_ci{
846881f68fSopenharmony_ci	(void)ino;
856881f68fSopenharmony_ci	req_clop(req)->ioctl(req, cmd, arg, fi, flags, in_buf, in_bufsz,
866881f68fSopenharmony_ci			     out_bufsz);
876881f68fSopenharmony_ci}
886881f68fSopenharmony_ci
896881f68fSopenharmony_cistatic void cuse_fll_poll(fuse_req_t req, fuse_ino_t ino,
906881f68fSopenharmony_ci			  struct fuse_file_info *fi, struct fuse_pollhandle *ph)
916881f68fSopenharmony_ci{
926881f68fSopenharmony_ci	(void)ino;
936881f68fSopenharmony_ci	req_clop(req)->poll(req, fi, ph);
946881f68fSopenharmony_ci}
956881f68fSopenharmony_ci
966881f68fSopenharmony_cistatic size_t cuse_pack_info(int argc, const char **argv, char *buf)
976881f68fSopenharmony_ci{
986881f68fSopenharmony_ci	size_t size = 0;
996881f68fSopenharmony_ci	int i;
1006881f68fSopenharmony_ci
1016881f68fSopenharmony_ci	for (i = 0; i < argc; i++) {
1026881f68fSopenharmony_ci		size_t len;
1036881f68fSopenharmony_ci
1046881f68fSopenharmony_ci		len = strlen(argv[i]) + 1;
1056881f68fSopenharmony_ci		size += len;
1066881f68fSopenharmony_ci		if (buf) {
1076881f68fSopenharmony_ci			memcpy(buf, argv[i], len);
1086881f68fSopenharmony_ci			buf += len;
1096881f68fSopenharmony_ci		}
1106881f68fSopenharmony_ci	}
1116881f68fSopenharmony_ci
1126881f68fSopenharmony_ci	return size;
1136881f68fSopenharmony_ci}
1146881f68fSopenharmony_ci
1156881f68fSopenharmony_cistatic struct cuse_data *cuse_prep_data(const struct cuse_info *ci,
1166881f68fSopenharmony_ci					const struct cuse_lowlevel_ops *clop)
1176881f68fSopenharmony_ci{
1186881f68fSopenharmony_ci	struct cuse_data *cd;
1196881f68fSopenharmony_ci	size_t dev_info_len;
1206881f68fSopenharmony_ci
1216881f68fSopenharmony_ci	dev_info_len = cuse_pack_info(ci->dev_info_argc, ci->dev_info_argv,
1226881f68fSopenharmony_ci				      NULL);
1236881f68fSopenharmony_ci
1246881f68fSopenharmony_ci	if (dev_info_len > CUSE_INIT_INFO_MAX) {
1256881f68fSopenharmony_ci		fuse_log(FUSE_LOG_ERR, "cuse: dev_info (%zu) too large, limit=%u\n",
1266881f68fSopenharmony_ci			dev_info_len, CUSE_INIT_INFO_MAX);
1276881f68fSopenharmony_ci		return NULL;
1286881f68fSopenharmony_ci	}
1296881f68fSopenharmony_ci
1306881f68fSopenharmony_ci	cd = calloc(1, sizeof(*cd) + dev_info_len);
1316881f68fSopenharmony_ci	if (!cd) {
1326881f68fSopenharmony_ci		fuse_log(FUSE_LOG_ERR, "cuse: failed to allocate cuse_data\n");
1336881f68fSopenharmony_ci		return NULL;
1346881f68fSopenharmony_ci	}
1356881f68fSopenharmony_ci
1366881f68fSopenharmony_ci	memcpy(&cd->clop, clop, sizeof(cd->clop));
1376881f68fSopenharmony_ci	cd->max_read = 131072;
1386881f68fSopenharmony_ci	cd->dev_major = ci->dev_major;
1396881f68fSopenharmony_ci	cd->dev_minor = ci->dev_minor;
1406881f68fSopenharmony_ci	cd->dev_info_len = dev_info_len;
1416881f68fSopenharmony_ci	cd->flags = ci->flags;
1426881f68fSopenharmony_ci	cuse_pack_info(ci->dev_info_argc, ci->dev_info_argv, cd->dev_info);
1436881f68fSopenharmony_ci
1446881f68fSopenharmony_ci	return cd;
1456881f68fSopenharmony_ci}
1466881f68fSopenharmony_ci
1476881f68fSopenharmony_cistruct fuse_session *cuse_lowlevel_new(struct fuse_args *args,
1486881f68fSopenharmony_ci				       const struct cuse_info *ci,
1496881f68fSopenharmony_ci				       const struct cuse_lowlevel_ops *clop,
1506881f68fSopenharmony_ci				       void *userdata)
1516881f68fSopenharmony_ci{
1526881f68fSopenharmony_ci	struct fuse_lowlevel_ops lop;
1536881f68fSopenharmony_ci	struct cuse_data *cd;
1546881f68fSopenharmony_ci	struct fuse_session *se;
1556881f68fSopenharmony_ci
1566881f68fSopenharmony_ci	cd = cuse_prep_data(ci, clop);
1576881f68fSopenharmony_ci	if (!cd)
1586881f68fSopenharmony_ci		return NULL;
1596881f68fSopenharmony_ci
1606881f68fSopenharmony_ci	memset(&lop, 0, sizeof(lop));
1616881f68fSopenharmony_ci	lop.init	= clop->init;
1626881f68fSopenharmony_ci	lop.destroy	= clop->destroy;
1636881f68fSopenharmony_ci	lop.open	= clop->open		? cuse_fll_open		: NULL;
1646881f68fSopenharmony_ci	lop.read	= clop->read		? cuse_fll_read		: NULL;
1656881f68fSopenharmony_ci	lop.write	= clop->write		? cuse_fll_write	: NULL;
1666881f68fSopenharmony_ci	lop.flush	= clop->flush		? cuse_fll_flush	: NULL;
1676881f68fSopenharmony_ci	lop.release	= clop->release		? cuse_fll_release	: NULL;
1686881f68fSopenharmony_ci	lop.fsync	= clop->fsync		? cuse_fll_fsync	: NULL;
1696881f68fSopenharmony_ci	lop.ioctl	= clop->ioctl		? cuse_fll_ioctl	: NULL;
1706881f68fSopenharmony_ci	lop.poll	= clop->poll		? cuse_fll_poll		: NULL;
1716881f68fSopenharmony_ci
1726881f68fSopenharmony_ci	se = fuse_session_new(args, &lop, sizeof(lop), userdata);
1736881f68fSopenharmony_ci	if (!se) {
1746881f68fSopenharmony_ci		free(cd);
1756881f68fSopenharmony_ci		return NULL;
1766881f68fSopenharmony_ci	}
1776881f68fSopenharmony_ci	se->cuse_data = cd;
1786881f68fSopenharmony_ci
1796881f68fSopenharmony_ci	return se;
1806881f68fSopenharmony_ci}
1816881f68fSopenharmony_ci
1826881f68fSopenharmony_cistatic int cuse_reply_init(fuse_req_t req, struct cuse_init_out *arg,
1836881f68fSopenharmony_ci			   char *dev_info, unsigned dev_info_len)
1846881f68fSopenharmony_ci{
1856881f68fSopenharmony_ci	struct iovec iov[3];
1866881f68fSopenharmony_ci
1876881f68fSopenharmony_ci	iov[1].iov_base = arg;
1886881f68fSopenharmony_ci	iov[1].iov_len = sizeof(struct cuse_init_out);
1896881f68fSopenharmony_ci	iov[2].iov_base = dev_info;
1906881f68fSopenharmony_ci	iov[2].iov_len = dev_info_len;
1916881f68fSopenharmony_ci
1926881f68fSopenharmony_ci	return fuse_send_reply_iov_nofree(req, 0, iov, 3);
1936881f68fSopenharmony_ci}
1946881f68fSopenharmony_ci
1956881f68fSopenharmony_civoid cuse_lowlevel_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1966881f68fSopenharmony_ci{
1976881f68fSopenharmony_ci	struct fuse_init_in *arg = (struct fuse_init_in *) inarg;
1986881f68fSopenharmony_ci	struct cuse_init_out outarg;
1996881f68fSopenharmony_ci	struct fuse_session *se = req->se;
2006881f68fSopenharmony_ci	struct cuse_data *cd = se->cuse_data;
2016881f68fSopenharmony_ci	size_t bufsize = se->bufsize;
2026881f68fSopenharmony_ci	struct cuse_lowlevel_ops *clop = req_clop(req);
2036881f68fSopenharmony_ci
2046881f68fSopenharmony_ci	(void) nodeid;
2056881f68fSopenharmony_ci	if (se->debug) {
2066881f68fSopenharmony_ci		fuse_log(FUSE_LOG_DEBUG, "CUSE_INIT: %u.%u\n", arg->major, arg->minor);
2076881f68fSopenharmony_ci		fuse_log(FUSE_LOG_DEBUG, "flags=0x%08x\n", arg->flags);
2086881f68fSopenharmony_ci	}
2096881f68fSopenharmony_ci	se->conn.proto_major = arg->major;
2106881f68fSopenharmony_ci	se->conn.proto_minor = arg->minor;
2116881f68fSopenharmony_ci	se->conn.capable = 0;
2126881f68fSopenharmony_ci	se->conn.want = 0;
2136881f68fSopenharmony_ci
2146881f68fSopenharmony_ci	if (arg->major < 7) {
2156881f68fSopenharmony_ci		fuse_log(FUSE_LOG_ERR, "cuse: unsupported protocol version: %u.%u\n",
2166881f68fSopenharmony_ci			arg->major, arg->minor);
2176881f68fSopenharmony_ci		fuse_reply_err(req, EPROTO);
2186881f68fSopenharmony_ci		return;
2196881f68fSopenharmony_ci	}
2206881f68fSopenharmony_ci
2216881f68fSopenharmony_ci	if (bufsize < FUSE_MIN_READ_BUFFER) {
2226881f68fSopenharmony_ci		fuse_log(FUSE_LOG_ERR, "cuse: warning: buffer size too small: %zu\n",
2236881f68fSopenharmony_ci			bufsize);
2246881f68fSopenharmony_ci		bufsize = FUSE_MIN_READ_BUFFER;
2256881f68fSopenharmony_ci	}
2266881f68fSopenharmony_ci
2276881f68fSopenharmony_ci	bufsize -= 4096;
2286881f68fSopenharmony_ci	if (bufsize < se->conn.max_write)
2296881f68fSopenharmony_ci		se->conn.max_write = bufsize;
2306881f68fSopenharmony_ci
2316881f68fSopenharmony_ci	se->got_init = 1;
2326881f68fSopenharmony_ci	if (se->op.init)
2336881f68fSopenharmony_ci		se->op.init(se->userdata, &se->conn);
2346881f68fSopenharmony_ci
2356881f68fSopenharmony_ci	memset(&outarg, 0, sizeof(outarg));
2366881f68fSopenharmony_ci	outarg.major = FUSE_KERNEL_VERSION;
2376881f68fSopenharmony_ci	outarg.minor = FUSE_KERNEL_MINOR_VERSION;
2386881f68fSopenharmony_ci	outarg.flags = cd->flags;
2396881f68fSopenharmony_ci	outarg.max_read = cd->max_read;
2406881f68fSopenharmony_ci	outarg.max_write = se->conn.max_write;
2416881f68fSopenharmony_ci	outarg.dev_major = cd->dev_major;
2426881f68fSopenharmony_ci	outarg.dev_minor = cd->dev_minor;
2436881f68fSopenharmony_ci
2446881f68fSopenharmony_ci	if (se->debug) {
2456881f68fSopenharmony_ci		fuse_log(FUSE_LOG_DEBUG, "   CUSE_INIT: %u.%u\n",
2466881f68fSopenharmony_ci			outarg.major, outarg.minor);
2476881f68fSopenharmony_ci		fuse_log(FUSE_LOG_DEBUG, "   flags=0x%08x\n", outarg.flags);
2486881f68fSopenharmony_ci		fuse_log(FUSE_LOG_DEBUG, "   max_read=0x%08x\n", outarg.max_read);
2496881f68fSopenharmony_ci		fuse_log(FUSE_LOG_DEBUG, "   max_write=0x%08x\n", outarg.max_write);
2506881f68fSopenharmony_ci		fuse_log(FUSE_LOG_DEBUG, "   dev_major=%u\n", outarg.dev_major);
2516881f68fSopenharmony_ci		fuse_log(FUSE_LOG_DEBUG, "   dev_minor=%u\n", outarg.dev_minor);
2526881f68fSopenharmony_ci		fuse_log(FUSE_LOG_DEBUG, "   dev_info: %.*s\n", cd->dev_info_len,
2536881f68fSopenharmony_ci			cd->dev_info);
2546881f68fSopenharmony_ci	}
2556881f68fSopenharmony_ci
2566881f68fSopenharmony_ci	cuse_reply_init(req, &outarg, cd->dev_info, cd->dev_info_len);
2576881f68fSopenharmony_ci
2586881f68fSopenharmony_ci	if (clop->init_done)
2596881f68fSopenharmony_ci		clop->init_done(se->userdata);
2606881f68fSopenharmony_ci
2616881f68fSopenharmony_ci	fuse_free_req(req);
2626881f68fSopenharmony_ci}
2636881f68fSopenharmony_ci
2646881f68fSopenharmony_cistruct fuse_session *cuse_lowlevel_setup(int argc, char *argv[],
2656881f68fSopenharmony_ci					 const struct cuse_info *ci,
2666881f68fSopenharmony_ci					 const struct cuse_lowlevel_ops *clop,
2676881f68fSopenharmony_ci					 int *multithreaded, void *userdata)
2686881f68fSopenharmony_ci{
2696881f68fSopenharmony_ci	const char *devname = "/dev/cuse";
2706881f68fSopenharmony_ci	static const struct fuse_opt kill_subtype_opts[] = {
2716881f68fSopenharmony_ci		FUSE_OPT_KEY("subtype=",  FUSE_OPT_KEY_DISCARD),
2726881f68fSopenharmony_ci		FUSE_OPT_END
2736881f68fSopenharmony_ci	};
2746881f68fSopenharmony_ci	struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
2756881f68fSopenharmony_ci	struct fuse_session *se;
2766881f68fSopenharmony_ci	struct fuse_cmdline_opts opts;
2776881f68fSopenharmony_ci	int fd;
2786881f68fSopenharmony_ci	int res;
2796881f68fSopenharmony_ci
2806881f68fSopenharmony_ci	if (fuse_parse_cmdline(&args, &opts) == -1)
2816881f68fSopenharmony_ci		return NULL;
2826881f68fSopenharmony_ci	*multithreaded = !opts.singlethread;
2836881f68fSopenharmony_ci
2846881f68fSopenharmony_ci	/* Remove subtype= option */
2856881f68fSopenharmony_ci	res = fuse_opt_parse(&args, NULL, kill_subtype_opts, NULL);
2866881f68fSopenharmony_ci	if (res == -1)
2876881f68fSopenharmony_ci		goto out1;
2886881f68fSopenharmony_ci
2896881f68fSopenharmony_ci	/*
2906881f68fSopenharmony_ci	 * Make sure file descriptors 0, 1 and 2 are open, otherwise chaos
2916881f68fSopenharmony_ci	 * would ensue.
2926881f68fSopenharmony_ci	 */
2936881f68fSopenharmony_ci	do {
2946881f68fSopenharmony_ci		fd = open("/dev/null", O_RDWR);
2956881f68fSopenharmony_ci		if (fd > 2)
2966881f68fSopenharmony_ci			close(fd);
2976881f68fSopenharmony_ci	} while (fd >= 0 && fd <= 2);
2986881f68fSopenharmony_ci
2996881f68fSopenharmony_ci	se = cuse_lowlevel_new(&args, ci, clop, userdata);
3006881f68fSopenharmony_ci	if (se == NULL)
3016881f68fSopenharmony_ci		goto out1;
3026881f68fSopenharmony_ci
3036881f68fSopenharmony_ci	fd = open(devname, O_RDWR);
3046881f68fSopenharmony_ci	if (fd == -1) {
3056881f68fSopenharmony_ci		if (errno == ENODEV || errno == ENOENT)
3066881f68fSopenharmony_ci			fuse_log(FUSE_LOG_ERR, "cuse: device not found, try 'modprobe cuse' first\n");
3076881f68fSopenharmony_ci		else
3086881f68fSopenharmony_ci			fuse_log(FUSE_LOG_ERR, "cuse: failed to open %s: %s\n",
3096881f68fSopenharmony_ci				devname, strerror(errno));
3106881f68fSopenharmony_ci		goto err_se;
3116881f68fSopenharmony_ci	}
3126881f68fSopenharmony_ci	se->fd = fd;
3136881f68fSopenharmony_ci
3146881f68fSopenharmony_ci	res = fuse_set_signal_handlers(se);
3156881f68fSopenharmony_ci	if (res == -1)
3166881f68fSopenharmony_ci		goto err_se;
3176881f68fSopenharmony_ci
3186881f68fSopenharmony_ci	res = fuse_daemonize(opts.foreground);
3196881f68fSopenharmony_ci	if (res == -1)
3206881f68fSopenharmony_ci		goto err_sig;
3216881f68fSopenharmony_ci
3226881f68fSopenharmony_ci	fuse_opt_free_args(&args);
3236881f68fSopenharmony_ci	return se;
3246881f68fSopenharmony_ci
3256881f68fSopenharmony_cierr_sig:
3266881f68fSopenharmony_ci	fuse_remove_signal_handlers(se);
3276881f68fSopenharmony_cierr_se:
3286881f68fSopenharmony_ci	fuse_session_destroy(se);
3296881f68fSopenharmony_ciout1:
3306881f68fSopenharmony_ci	free(opts.mountpoint);
3316881f68fSopenharmony_ci	fuse_opt_free_args(&args);
3326881f68fSopenharmony_ci	return NULL;
3336881f68fSopenharmony_ci}
3346881f68fSopenharmony_ci
3356881f68fSopenharmony_civoid cuse_lowlevel_teardown(struct fuse_session *se)
3366881f68fSopenharmony_ci{
3376881f68fSopenharmony_ci	fuse_remove_signal_handlers(se);
3386881f68fSopenharmony_ci	fuse_session_destroy(se);
3396881f68fSopenharmony_ci}
3406881f68fSopenharmony_ci
3416881f68fSopenharmony_ciint cuse_lowlevel_main(int argc, char *argv[], const struct cuse_info *ci,
3426881f68fSopenharmony_ci		       const struct cuse_lowlevel_ops *clop, void *userdata)
3436881f68fSopenharmony_ci{
3446881f68fSopenharmony_ci	struct fuse_session *se;
3456881f68fSopenharmony_ci	int multithreaded;
3466881f68fSopenharmony_ci	int res;
3476881f68fSopenharmony_ci
3486881f68fSopenharmony_ci	se = cuse_lowlevel_setup(argc, argv, ci, clop, &multithreaded,
3496881f68fSopenharmony_ci				 userdata);
3506881f68fSopenharmony_ci	if (se == NULL)
3516881f68fSopenharmony_ci		return 1;
3526881f68fSopenharmony_ci
3536881f68fSopenharmony_ci	if (multithreaded) {
3546881f68fSopenharmony_ci		struct fuse_loop_config *config = fuse_loop_cfg_create();
3556881f68fSopenharmony_ci		res = fuse_session_loop_mt(se, config);
3566881f68fSopenharmony_ci		fuse_loop_cfg_destroy(config);
3576881f68fSopenharmony_ci	}
3586881f68fSopenharmony_ci	else
3596881f68fSopenharmony_ci		res = fuse_session_loop(se);
3606881f68fSopenharmony_ci
3616881f68fSopenharmony_ci	cuse_lowlevel_teardown(se);
3626881f68fSopenharmony_ci	if (res == -1)
3636881f68fSopenharmony_ci		return 1;
3646881f68fSopenharmony_ci
3656881f68fSopenharmony_ci	return 0;
3666881f68fSopenharmony_ci}
367