xref: /aosp_15_r20/external/libfuse/lib/fuse_lowlevel.c (revision 9e5649576b786774a32d7b0252c9cd8c6538fa49)
1*9e564957SAndroid Build Coastguard Worker /*
2*9e564957SAndroid Build Coastguard Worker   FUSE: Filesystem in Userspace
3*9e564957SAndroid Build Coastguard Worker   Copyright (C) 2001-2007  Miklos Szeredi <[email protected]>
4*9e564957SAndroid Build Coastguard Worker 
5*9e564957SAndroid Build Coastguard Worker   Implementation of (most of) the low-level FUSE API. The session loop
6*9e564957SAndroid Build Coastguard Worker   functions are implemented in separate files.
7*9e564957SAndroid Build Coastguard Worker 
8*9e564957SAndroid Build Coastguard Worker   This program can be distributed under the terms of the GNU LGPLv2.
9*9e564957SAndroid Build Coastguard Worker   See the file COPYING.LIB
10*9e564957SAndroid Build Coastguard Worker */
11*9e564957SAndroid Build Coastguard Worker 
12*9e564957SAndroid Build Coastguard Worker #define _GNU_SOURCE
13*9e564957SAndroid Build Coastguard Worker 
14*9e564957SAndroid Build Coastguard Worker #include "fuse_config.h"
15*9e564957SAndroid Build Coastguard Worker #include "fuse_i.h"
16*9e564957SAndroid Build Coastguard Worker #include "fuse_kernel.h"
17*9e564957SAndroid Build Coastguard Worker #include "fuse_opt.h"
18*9e564957SAndroid Build Coastguard Worker #include "fuse_misc.h"
19*9e564957SAndroid Build Coastguard Worker #include "mount_util.h"
20*9e564957SAndroid Build Coastguard Worker 
21*9e564957SAndroid Build Coastguard Worker #include <stdio.h>
22*9e564957SAndroid Build Coastguard Worker #include <stdlib.h>
23*9e564957SAndroid Build Coastguard Worker #include <stddef.h>
24*9e564957SAndroid Build Coastguard Worker #include <string.h>
25*9e564957SAndroid Build Coastguard Worker #include <unistd.h>
26*9e564957SAndroid Build Coastguard Worker #include <limits.h>
27*9e564957SAndroid Build Coastguard Worker #include <errno.h>
28*9e564957SAndroid Build Coastguard Worker #include <assert.h>
29*9e564957SAndroid Build Coastguard Worker #include <sys/file.h>
30*9e564957SAndroid Build Coastguard Worker #include <sys/ioctl.h>
31*9e564957SAndroid Build Coastguard Worker 
32*9e564957SAndroid Build Coastguard Worker #ifndef F_LINUX_SPECIFIC_BASE
33*9e564957SAndroid Build Coastguard Worker #define F_LINUX_SPECIFIC_BASE       1024
34*9e564957SAndroid Build Coastguard Worker #endif
35*9e564957SAndroid Build Coastguard Worker #ifndef F_SETPIPE_SZ
36*9e564957SAndroid Build Coastguard Worker #define F_SETPIPE_SZ	(F_LINUX_SPECIFIC_BASE + 7)
37*9e564957SAndroid Build Coastguard Worker #endif
38*9e564957SAndroid Build Coastguard Worker 
39*9e564957SAndroid Build Coastguard Worker 
40*9e564957SAndroid Build Coastguard Worker #define PARAM(inarg) (((char *)(inarg)) + sizeof(*(inarg)))
41*9e564957SAndroid Build Coastguard Worker #define OFFSET_MAX 0x7fffffffffffffffLL
42*9e564957SAndroid Build Coastguard Worker 
43*9e564957SAndroid Build Coastguard Worker #define container_of(ptr, type, member) ({				\
44*9e564957SAndroid Build Coastguard Worker 			const typeof( ((type *)0)->member ) *__mptr = (ptr); \
45*9e564957SAndroid Build Coastguard Worker 			(type *)( (char *)__mptr - offsetof(type,member) );})
46*9e564957SAndroid Build Coastguard Worker 
47*9e564957SAndroid Build Coastguard Worker struct fuse_pollhandle {
48*9e564957SAndroid Build Coastguard Worker 	uint64_t kh;
49*9e564957SAndroid Build Coastguard Worker 	struct fuse_session *se;
50*9e564957SAndroid Build Coastguard Worker };
51*9e564957SAndroid Build Coastguard Worker 
52*9e564957SAndroid Build Coastguard Worker static size_t pagesize;
53*9e564957SAndroid Build Coastguard Worker 
fuse_ll_init_pagesize(void)54*9e564957SAndroid Build Coastguard Worker static __attribute__((constructor)) void fuse_ll_init_pagesize(void)
55*9e564957SAndroid Build Coastguard Worker {
56*9e564957SAndroid Build Coastguard Worker 	pagesize = getpagesize();
57*9e564957SAndroid Build Coastguard Worker }
58*9e564957SAndroid Build Coastguard Worker 
convert_stat(const struct stat * stbuf,struct fuse_attr * attr)59*9e564957SAndroid Build Coastguard Worker static void convert_stat(const struct stat *stbuf, struct fuse_attr *attr)
60*9e564957SAndroid Build Coastguard Worker {
61*9e564957SAndroid Build Coastguard Worker 	attr->ino	= stbuf->st_ino;
62*9e564957SAndroid Build Coastguard Worker 	attr->mode	= stbuf->st_mode;
63*9e564957SAndroid Build Coastguard Worker 	attr->nlink	= stbuf->st_nlink;
64*9e564957SAndroid Build Coastguard Worker 	attr->uid	= stbuf->st_uid;
65*9e564957SAndroid Build Coastguard Worker 	attr->gid	= stbuf->st_gid;
66*9e564957SAndroid Build Coastguard Worker 	attr->rdev	= stbuf->st_rdev;
67*9e564957SAndroid Build Coastguard Worker 	attr->size	= stbuf->st_size;
68*9e564957SAndroid Build Coastguard Worker 	attr->blksize	= stbuf->st_blksize;
69*9e564957SAndroid Build Coastguard Worker 	attr->blocks	= stbuf->st_blocks;
70*9e564957SAndroid Build Coastguard Worker 	attr->atime	= stbuf->st_atime;
71*9e564957SAndroid Build Coastguard Worker 	attr->mtime	= stbuf->st_mtime;
72*9e564957SAndroid Build Coastguard Worker 	attr->ctime	= stbuf->st_ctime;
73*9e564957SAndroid Build Coastguard Worker 	attr->atimensec = ST_ATIM_NSEC(stbuf);
74*9e564957SAndroid Build Coastguard Worker 	attr->mtimensec = ST_MTIM_NSEC(stbuf);
75*9e564957SAndroid Build Coastguard Worker 	attr->ctimensec = ST_CTIM_NSEC(stbuf);
76*9e564957SAndroid Build Coastguard Worker }
77*9e564957SAndroid Build Coastguard Worker 
convert_attr(const struct fuse_setattr_in * attr,struct stat * stbuf)78*9e564957SAndroid Build Coastguard Worker static void convert_attr(const struct fuse_setattr_in *attr, struct stat *stbuf)
79*9e564957SAndroid Build Coastguard Worker {
80*9e564957SAndroid Build Coastguard Worker 	stbuf->st_mode	       = attr->mode;
81*9e564957SAndroid Build Coastguard Worker 	stbuf->st_uid	       = attr->uid;
82*9e564957SAndroid Build Coastguard Worker 	stbuf->st_gid	       = attr->gid;
83*9e564957SAndroid Build Coastguard Worker 	stbuf->st_size	       = attr->size;
84*9e564957SAndroid Build Coastguard Worker 	stbuf->st_atime	       = attr->atime;
85*9e564957SAndroid Build Coastguard Worker 	stbuf->st_mtime	       = attr->mtime;
86*9e564957SAndroid Build Coastguard Worker 	stbuf->st_ctime        = attr->ctime;
87*9e564957SAndroid Build Coastguard Worker 	ST_ATIM_NSEC_SET(stbuf, attr->atimensec);
88*9e564957SAndroid Build Coastguard Worker 	ST_MTIM_NSEC_SET(stbuf, attr->mtimensec);
89*9e564957SAndroid Build Coastguard Worker 	ST_CTIM_NSEC_SET(stbuf, attr->ctimensec);
90*9e564957SAndroid Build Coastguard Worker }
91*9e564957SAndroid Build Coastguard Worker 
iov_length(const struct iovec * iov,size_t count)92*9e564957SAndroid Build Coastguard Worker static	size_t iov_length(const struct iovec *iov, size_t count)
93*9e564957SAndroid Build Coastguard Worker {
94*9e564957SAndroid Build Coastguard Worker 	size_t seg;
95*9e564957SAndroid Build Coastguard Worker 	size_t ret = 0;
96*9e564957SAndroid Build Coastguard Worker 
97*9e564957SAndroid Build Coastguard Worker 	for (seg = 0; seg < count; seg++)
98*9e564957SAndroid Build Coastguard Worker 		ret += iov[seg].iov_len;
99*9e564957SAndroid Build Coastguard Worker 	return ret;
100*9e564957SAndroid Build Coastguard Worker }
101*9e564957SAndroid Build Coastguard Worker 
list_init_req(struct fuse_req * req)102*9e564957SAndroid Build Coastguard Worker static void list_init_req(struct fuse_req *req)
103*9e564957SAndroid Build Coastguard Worker {
104*9e564957SAndroid Build Coastguard Worker 	req->next = req;
105*9e564957SAndroid Build Coastguard Worker 	req->prev = req;
106*9e564957SAndroid Build Coastguard Worker }
107*9e564957SAndroid Build Coastguard Worker 
list_del_req(struct fuse_req * req)108*9e564957SAndroid Build Coastguard Worker static void list_del_req(struct fuse_req *req)
109*9e564957SAndroid Build Coastguard Worker {
110*9e564957SAndroid Build Coastguard Worker 	struct fuse_req *prev = req->prev;
111*9e564957SAndroid Build Coastguard Worker 	struct fuse_req *next = req->next;
112*9e564957SAndroid Build Coastguard Worker 	prev->next = next;
113*9e564957SAndroid Build Coastguard Worker 	next->prev = prev;
114*9e564957SAndroid Build Coastguard Worker }
115*9e564957SAndroid Build Coastguard Worker 
list_add_req(struct fuse_req * req,struct fuse_req * next)116*9e564957SAndroid Build Coastguard Worker static void list_add_req(struct fuse_req *req, struct fuse_req *next)
117*9e564957SAndroid Build Coastguard Worker {
118*9e564957SAndroid Build Coastguard Worker 	struct fuse_req *prev = next->prev;
119*9e564957SAndroid Build Coastguard Worker 	req->next = next;
120*9e564957SAndroid Build Coastguard Worker 	req->prev = prev;
121*9e564957SAndroid Build Coastguard Worker 	prev->next = req;
122*9e564957SAndroid Build Coastguard Worker 	next->prev = req;
123*9e564957SAndroid Build Coastguard Worker }
124*9e564957SAndroid Build Coastguard Worker 
destroy_req(fuse_req_t req)125*9e564957SAndroid Build Coastguard Worker static void destroy_req(fuse_req_t req)
126*9e564957SAndroid Build Coastguard Worker {
127*9e564957SAndroid Build Coastguard Worker 	assert(req->ch == NULL);
128*9e564957SAndroid Build Coastguard Worker 	pthread_mutex_destroy(&req->lock);
129*9e564957SAndroid Build Coastguard Worker 	free(req);
130*9e564957SAndroid Build Coastguard Worker }
131*9e564957SAndroid Build Coastguard Worker 
fuse_free_req(fuse_req_t req)132*9e564957SAndroid Build Coastguard Worker void fuse_free_req(fuse_req_t req)
133*9e564957SAndroid Build Coastguard Worker {
134*9e564957SAndroid Build Coastguard Worker 	int ctr;
135*9e564957SAndroid Build Coastguard Worker 	struct fuse_session *se = req->se;
136*9e564957SAndroid Build Coastguard Worker 
137*9e564957SAndroid Build Coastguard Worker 	pthread_mutex_lock(&se->lock);
138*9e564957SAndroid Build Coastguard Worker 	req->u.ni.func = NULL;
139*9e564957SAndroid Build Coastguard Worker 	req->u.ni.data = NULL;
140*9e564957SAndroid Build Coastguard Worker 	list_del_req(req);
141*9e564957SAndroid Build Coastguard Worker 	ctr = --req->ctr;
142*9e564957SAndroid Build Coastguard Worker 	fuse_chan_put(req->ch);
143*9e564957SAndroid Build Coastguard Worker 	req->ch = NULL;
144*9e564957SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&se->lock);
145*9e564957SAndroid Build Coastguard Worker 	if (!ctr)
146*9e564957SAndroid Build Coastguard Worker 		destroy_req(req);
147*9e564957SAndroid Build Coastguard Worker }
148*9e564957SAndroid Build Coastguard Worker 
fuse_ll_alloc_req(struct fuse_session * se)149*9e564957SAndroid Build Coastguard Worker static struct fuse_req *fuse_ll_alloc_req(struct fuse_session *se)
150*9e564957SAndroid Build Coastguard Worker {
151*9e564957SAndroid Build Coastguard Worker 	struct fuse_req *req;
152*9e564957SAndroid Build Coastguard Worker 
153*9e564957SAndroid Build Coastguard Worker 	req = (struct fuse_req *) calloc(1, sizeof(struct fuse_req));
154*9e564957SAndroid Build Coastguard Worker 	if (req == NULL) {
155*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: failed to allocate request\n");
156*9e564957SAndroid Build Coastguard Worker 	} else {
157*9e564957SAndroid Build Coastguard Worker 		req->se = se;
158*9e564957SAndroid Build Coastguard Worker 		req->ctr = 1;
159*9e564957SAndroid Build Coastguard Worker 		list_init_req(req);
160*9e564957SAndroid Build Coastguard Worker 		pthread_mutex_init(&req->lock, NULL);
161*9e564957SAndroid Build Coastguard Worker 	}
162*9e564957SAndroid Build Coastguard Worker 
163*9e564957SAndroid Build Coastguard Worker 	return req;
164*9e564957SAndroid Build Coastguard Worker }
165*9e564957SAndroid Build Coastguard Worker 
166*9e564957SAndroid Build Coastguard Worker /* Send data. If *ch* is NULL, send via session master fd */
fuse_send_msg(struct fuse_session * se,struct fuse_chan * ch,struct iovec * iov,int count)167*9e564957SAndroid Build Coastguard Worker static int fuse_send_msg(struct fuse_session *se, struct fuse_chan *ch,
168*9e564957SAndroid Build Coastguard Worker 			 struct iovec *iov, int count)
169*9e564957SAndroid Build Coastguard Worker {
170*9e564957SAndroid Build Coastguard Worker 	struct fuse_out_header *out = iov[0].iov_base;
171*9e564957SAndroid Build Coastguard Worker 
172*9e564957SAndroid Build Coastguard Worker 	assert(se != NULL);
173*9e564957SAndroid Build Coastguard Worker 	out->len = iov_length(iov, count);
174*9e564957SAndroid Build Coastguard Worker 	if (se->debug) {
175*9e564957SAndroid Build Coastguard Worker 		if (out->unique == 0) {
176*9e564957SAndroid Build Coastguard Worker 			fuse_log(FUSE_LOG_DEBUG, "NOTIFY: code=%d length=%u\n",
177*9e564957SAndroid Build Coastguard Worker 				out->error, out->len);
178*9e564957SAndroid Build Coastguard Worker 		} else if (out->error) {
179*9e564957SAndroid Build Coastguard Worker 			fuse_log(FUSE_LOG_DEBUG,
180*9e564957SAndroid Build Coastguard Worker 				"   unique: %llu, error: %i (%s), outsize: %i\n",
181*9e564957SAndroid Build Coastguard Worker 				(unsigned long long) out->unique, out->error,
182*9e564957SAndroid Build Coastguard Worker 				strerror(-out->error), out->len);
183*9e564957SAndroid Build Coastguard Worker 		} else {
184*9e564957SAndroid Build Coastguard Worker 			fuse_log(FUSE_LOG_DEBUG,
185*9e564957SAndroid Build Coastguard Worker 				"   unique: %llu, success, outsize: %i\n",
186*9e564957SAndroid Build Coastguard Worker 				(unsigned long long) out->unique, out->len);
187*9e564957SAndroid Build Coastguard Worker 		}
188*9e564957SAndroid Build Coastguard Worker 	}
189*9e564957SAndroid Build Coastguard Worker 
190*9e564957SAndroid Build Coastguard Worker 	ssize_t res;
191*9e564957SAndroid Build Coastguard Worker 	if (se->io != NULL)
192*9e564957SAndroid Build Coastguard Worker 		/* se->io->writev is never NULL if se->io is not NULL as
193*9e564957SAndroid Build Coastguard Worker 		specified by fuse_session_custom_io()*/
194*9e564957SAndroid Build Coastguard Worker 		res = se->io->writev(ch ? ch->fd : se->fd, iov, count,
195*9e564957SAndroid Build Coastguard Worker 					   se->userdata);
196*9e564957SAndroid Build Coastguard Worker 	else
197*9e564957SAndroid Build Coastguard Worker 		res = writev(ch ? ch->fd : se->fd, iov, count);
198*9e564957SAndroid Build Coastguard Worker 
199*9e564957SAndroid Build Coastguard Worker 	int err = errno;
200*9e564957SAndroid Build Coastguard Worker 
201*9e564957SAndroid Build Coastguard Worker 	if (res == -1) {
202*9e564957SAndroid Build Coastguard Worker 		/* ENOENT means the operation was interrupted */
203*9e564957SAndroid Build Coastguard Worker 		if (!fuse_session_exited(se) && err != ENOENT)
204*9e564957SAndroid Build Coastguard Worker 			perror("fuse: writing device");
205*9e564957SAndroid Build Coastguard Worker 		return -err;
206*9e564957SAndroid Build Coastguard Worker 	}
207*9e564957SAndroid Build Coastguard Worker 
208*9e564957SAndroid Build Coastguard Worker 	return 0;
209*9e564957SAndroid Build Coastguard Worker }
210*9e564957SAndroid Build Coastguard Worker 
211*9e564957SAndroid Build Coastguard Worker 
fuse_send_reply_iov_nofree(fuse_req_t req,int error,struct iovec * iov,int count)212*9e564957SAndroid Build Coastguard Worker int fuse_send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov,
213*9e564957SAndroid Build Coastguard Worker 			       int count)
214*9e564957SAndroid Build Coastguard Worker {
215*9e564957SAndroid Build Coastguard Worker 	struct fuse_out_header out;
216*9e564957SAndroid Build Coastguard Worker 
217*9e564957SAndroid Build Coastguard Worker #if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 32
218*9e564957SAndroid Build Coastguard Worker 	const char *str = strerrordesc_np(error * -1);
219*9e564957SAndroid Build Coastguard Worker 	if ((str == NULL && error != 0) || error > 0) {
220*9e564957SAndroid Build Coastguard Worker #else
221*9e564957SAndroid Build Coastguard Worker 	if (error <= -1000 || error > 0) {
222*9e564957SAndroid Build Coastguard Worker #endif
223*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: bad error value: %i\n",	error);
224*9e564957SAndroid Build Coastguard Worker 		error = -ERANGE;
225*9e564957SAndroid Build Coastguard Worker 	}
226*9e564957SAndroid Build Coastguard Worker 
227*9e564957SAndroid Build Coastguard Worker 	out.unique = req->unique;
228*9e564957SAndroid Build Coastguard Worker 	out.error = error;
229*9e564957SAndroid Build Coastguard Worker 
230*9e564957SAndroid Build Coastguard Worker 	iov[0].iov_base = &out;
231*9e564957SAndroid Build Coastguard Worker 	iov[0].iov_len = sizeof(struct fuse_out_header);
232*9e564957SAndroid Build Coastguard Worker 
233*9e564957SAndroid Build Coastguard Worker 	return fuse_send_msg(req->se, req->ch, iov, count);
234*9e564957SAndroid Build Coastguard Worker }
235*9e564957SAndroid Build Coastguard Worker 
236*9e564957SAndroid Build Coastguard Worker static int send_reply_iov(fuse_req_t req, int error, struct iovec *iov,
237*9e564957SAndroid Build Coastguard Worker 			  int count)
238*9e564957SAndroid Build Coastguard Worker {
239*9e564957SAndroid Build Coastguard Worker 	int res;
240*9e564957SAndroid Build Coastguard Worker 
241*9e564957SAndroid Build Coastguard Worker 	res = fuse_send_reply_iov_nofree(req, error, iov, count);
242*9e564957SAndroid Build Coastguard Worker 	fuse_free_req(req);
243*9e564957SAndroid Build Coastguard Worker 	return res;
244*9e564957SAndroid Build Coastguard Worker }
245*9e564957SAndroid Build Coastguard Worker 
246*9e564957SAndroid Build Coastguard Worker static int send_reply(fuse_req_t req, int error, const void *arg,
247*9e564957SAndroid Build Coastguard Worker 		      size_t argsize)
248*9e564957SAndroid Build Coastguard Worker {
249*9e564957SAndroid Build Coastguard Worker 	struct iovec iov[2];
250*9e564957SAndroid Build Coastguard Worker 	int count = 1;
251*9e564957SAndroid Build Coastguard Worker 	if (argsize) {
252*9e564957SAndroid Build Coastguard Worker 		iov[1].iov_base = (void *) arg;
253*9e564957SAndroid Build Coastguard Worker 		iov[1].iov_len = argsize;
254*9e564957SAndroid Build Coastguard Worker 		count++;
255*9e564957SAndroid Build Coastguard Worker 	}
256*9e564957SAndroid Build Coastguard Worker 	return send_reply_iov(req, error, iov, count);
257*9e564957SAndroid Build Coastguard Worker }
258*9e564957SAndroid Build Coastguard Worker 
259*9e564957SAndroid Build Coastguard Worker int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count)
260*9e564957SAndroid Build Coastguard Worker {
261*9e564957SAndroid Build Coastguard Worker 	int res;
262*9e564957SAndroid Build Coastguard Worker 	struct iovec *padded_iov;
263*9e564957SAndroid Build Coastguard Worker 
264*9e564957SAndroid Build Coastguard Worker 	padded_iov = malloc((count + 1) * sizeof(struct iovec));
265*9e564957SAndroid Build Coastguard Worker 	if (padded_iov == NULL)
266*9e564957SAndroid Build Coastguard Worker 		return fuse_reply_err(req, ENOMEM);
267*9e564957SAndroid Build Coastguard Worker 
268*9e564957SAndroid Build Coastguard Worker 	memcpy(padded_iov + 1, iov, count * sizeof(struct iovec));
269*9e564957SAndroid Build Coastguard Worker 	count++;
270*9e564957SAndroid Build Coastguard Worker 
271*9e564957SAndroid Build Coastguard Worker 	res = send_reply_iov(req, 0, padded_iov, count);
272*9e564957SAndroid Build Coastguard Worker 	free(padded_iov);
273*9e564957SAndroid Build Coastguard Worker 
274*9e564957SAndroid Build Coastguard Worker 	return res;
275*9e564957SAndroid Build Coastguard Worker }
276*9e564957SAndroid Build Coastguard Worker 
277*9e564957SAndroid Build Coastguard Worker 
278*9e564957SAndroid Build Coastguard Worker /* `buf` is allowed to be empty so that the proper size may be
279*9e564957SAndroid Build Coastguard Worker    allocated by the caller */
280*9e564957SAndroid Build Coastguard Worker size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize,
281*9e564957SAndroid Build Coastguard Worker 			 const char *name, const struct stat *stbuf, off_t off)
282*9e564957SAndroid Build Coastguard Worker {
283*9e564957SAndroid Build Coastguard Worker 	(void)req;
284*9e564957SAndroid Build Coastguard Worker 	size_t namelen;
285*9e564957SAndroid Build Coastguard Worker 	size_t entlen;
286*9e564957SAndroid Build Coastguard Worker 	size_t entlen_padded;
287*9e564957SAndroid Build Coastguard Worker 	struct fuse_dirent *dirent;
288*9e564957SAndroid Build Coastguard Worker 
289*9e564957SAndroid Build Coastguard Worker 	namelen = strlen(name);
290*9e564957SAndroid Build Coastguard Worker 	entlen = FUSE_NAME_OFFSET + namelen;
291*9e564957SAndroid Build Coastguard Worker 	entlen_padded = FUSE_DIRENT_ALIGN(entlen);
292*9e564957SAndroid Build Coastguard Worker 
293*9e564957SAndroid Build Coastguard Worker 	if ((buf == NULL) || (entlen_padded > bufsize))
294*9e564957SAndroid Build Coastguard Worker 	  return entlen_padded;
295*9e564957SAndroid Build Coastguard Worker 
296*9e564957SAndroid Build Coastguard Worker 	dirent = (struct fuse_dirent*) buf;
297*9e564957SAndroid Build Coastguard Worker 	dirent->ino = stbuf->st_ino;
298*9e564957SAndroid Build Coastguard Worker 	dirent->off = off;
299*9e564957SAndroid Build Coastguard Worker 	dirent->namelen = namelen;
300*9e564957SAndroid Build Coastguard Worker 	dirent->type = (stbuf->st_mode & S_IFMT) >> 12;
301*9e564957SAndroid Build Coastguard Worker 	memcpy(dirent->name, name, namelen);
302*9e564957SAndroid Build Coastguard Worker 	memset(dirent->name + namelen, 0, entlen_padded - entlen);
303*9e564957SAndroid Build Coastguard Worker 
304*9e564957SAndroid Build Coastguard Worker 	return entlen_padded;
305*9e564957SAndroid Build Coastguard Worker }
306*9e564957SAndroid Build Coastguard Worker 
307*9e564957SAndroid Build Coastguard Worker static void convert_statfs(const struct statvfs *stbuf,
308*9e564957SAndroid Build Coastguard Worker 			   struct fuse_kstatfs *kstatfs)
309*9e564957SAndroid Build Coastguard Worker {
310*9e564957SAndroid Build Coastguard Worker 	kstatfs->bsize	 = stbuf->f_bsize;
311*9e564957SAndroid Build Coastguard Worker 	kstatfs->frsize	 = stbuf->f_frsize;
312*9e564957SAndroid Build Coastguard Worker 	kstatfs->blocks	 = stbuf->f_blocks;
313*9e564957SAndroid Build Coastguard Worker 	kstatfs->bfree	 = stbuf->f_bfree;
314*9e564957SAndroid Build Coastguard Worker 	kstatfs->bavail	 = stbuf->f_bavail;
315*9e564957SAndroid Build Coastguard Worker 	kstatfs->files	 = stbuf->f_files;
316*9e564957SAndroid Build Coastguard Worker 	kstatfs->ffree	 = stbuf->f_ffree;
317*9e564957SAndroid Build Coastguard Worker 	kstatfs->namelen = stbuf->f_namemax;
318*9e564957SAndroid Build Coastguard Worker }
319*9e564957SAndroid Build Coastguard Worker 
320*9e564957SAndroid Build Coastguard Worker static int send_reply_ok(fuse_req_t req, const void *arg, size_t argsize)
321*9e564957SAndroid Build Coastguard Worker {
322*9e564957SAndroid Build Coastguard Worker 	return send_reply(req, 0, arg, argsize);
323*9e564957SAndroid Build Coastguard Worker }
324*9e564957SAndroid Build Coastguard Worker 
325*9e564957SAndroid Build Coastguard Worker int fuse_reply_err(fuse_req_t req, int err)
326*9e564957SAndroid Build Coastguard Worker {
327*9e564957SAndroid Build Coastguard Worker 	return send_reply(req, -err, NULL, 0);
328*9e564957SAndroid Build Coastguard Worker }
329*9e564957SAndroid Build Coastguard Worker 
330*9e564957SAndroid Build Coastguard Worker void fuse_reply_none(fuse_req_t req)
331*9e564957SAndroid Build Coastguard Worker {
332*9e564957SAndroid Build Coastguard Worker 	fuse_free_req(req);
333*9e564957SAndroid Build Coastguard Worker }
334*9e564957SAndroid Build Coastguard Worker 
335*9e564957SAndroid Build Coastguard Worker static unsigned long calc_timeout_sec(double t)
336*9e564957SAndroid Build Coastguard Worker {
337*9e564957SAndroid Build Coastguard Worker 	if (t > (double) ULONG_MAX)
338*9e564957SAndroid Build Coastguard Worker 		return ULONG_MAX;
339*9e564957SAndroid Build Coastguard Worker 	else if (t < 0.0)
340*9e564957SAndroid Build Coastguard Worker 		return 0;
341*9e564957SAndroid Build Coastguard Worker 	else
342*9e564957SAndroid Build Coastguard Worker 		return (unsigned long) t;
343*9e564957SAndroid Build Coastguard Worker }
344*9e564957SAndroid Build Coastguard Worker 
345*9e564957SAndroid Build Coastguard Worker static unsigned int calc_timeout_nsec(double t)
346*9e564957SAndroid Build Coastguard Worker {
347*9e564957SAndroid Build Coastguard Worker 	double f = t - (double) calc_timeout_sec(t);
348*9e564957SAndroid Build Coastguard Worker 	if (f < 0.0)
349*9e564957SAndroid Build Coastguard Worker 		return 0;
350*9e564957SAndroid Build Coastguard Worker 	else if (f >= 0.999999999)
351*9e564957SAndroid Build Coastguard Worker 		return 999999999;
352*9e564957SAndroid Build Coastguard Worker 	else
353*9e564957SAndroid Build Coastguard Worker 		return (unsigned int) (f * 1.0e9);
354*9e564957SAndroid Build Coastguard Worker }
355*9e564957SAndroid Build Coastguard Worker 
356*9e564957SAndroid Build Coastguard Worker static void fill_entry(struct fuse_entry_out *arg,
357*9e564957SAndroid Build Coastguard Worker 		       const struct fuse_entry_param *e)
358*9e564957SAndroid Build Coastguard Worker {
359*9e564957SAndroid Build Coastguard Worker 	arg->nodeid = e->ino;
360*9e564957SAndroid Build Coastguard Worker 	arg->generation = e->generation;
361*9e564957SAndroid Build Coastguard Worker 	arg->entry_valid = calc_timeout_sec(e->entry_timeout);
362*9e564957SAndroid Build Coastguard Worker 	arg->entry_valid_nsec = calc_timeout_nsec(e->entry_timeout);
363*9e564957SAndroid Build Coastguard Worker 	arg->attr_valid = calc_timeout_sec(e->attr_timeout);
364*9e564957SAndroid Build Coastguard Worker 	arg->attr_valid_nsec = calc_timeout_nsec(e->attr_timeout);
365*9e564957SAndroid Build Coastguard Worker 	convert_stat(&e->attr, &arg->attr);
366*9e564957SAndroid Build Coastguard Worker }
367*9e564957SAndroid Build Coastguard Worker 
368*9e564957SAndroid Build Coastguard Worker /* `buf` is allowed to be empty so that the proper size may be
369*9e564957SAndroid Build Coastguard Worker    allocated by the caller */
370*9e564957SAndroid Build Coastguard Worker size_t fuse_add_direntry_plus(fuse_req_t req, char *buf, size_t bufsize,
371*9e564957SAndroid Build Coastguard Worker 			      const char *name,
372*9e564957SAndroid Build Coastguard Worker 			      const struct fuse_entry_param *e, off_t off)
373*9e564957SAndroid Build Coastguard Worker {
374*9e564957SAndroid Build Coastguard Worker 	(void)req;
375*9e564957SAndroid Build Coastguard Worker 	size_t namelen;
376*9e564957SAndroid Build Coastguard Worker 	size_t entlen;
377*9e564957SAndroid Build Coastguard Worker 	size_t entlen_padded;
378*9e564957SAndroid Build Coastguard Worker 
379*9e564957SAndroid Build Coastguard Worker 	namelen = strlen(name);
380*9e564957SAndroid Build Coastguard Worker 	entlen = FUSE_NAME_OFFSET_DIRENTPLUS + namelen;
381*9e564957SAndroid Build Coastguard Worker 	entlen_padded = FUSE_DIRENT_ALIGN(entlen);
382*9e564957SAndroid Build Coastguard Worker 	if ((buf == NULL) || (entlen_padded > bufsize))
383*9e564957SAndroid Build Coastguard Worker 	  return entlen_padded;
384*9e564957SAndroid Build Coastguard Worker 
385*9e564957SAndroid Build Coastguard Worker 	struct fuse_direntplus *dp = (struct fuse_direntplus *) buf;
386*9e564957SAndroid Build Coastguard Worker 	memset(&dp->entry_out, 0, sizeof(dp->entry_out));
387*9e564957SAndroid Build Coastguard Worker 	fill_entry(&dp->entry_out, e);
388*9e564957SAndroid Build Coastguard Worker 
389*9e564957SAndroid Build Coastguard Worker 	struct fuse_dirent *dirent = &dp->dirent;
390*9e564957SAndroid Build Coastguard Worker 	dirent->ino = e->attr.st_ino;
391*9e564957SAndroid Build Coastguard Worker 	dirent->off = off;
392*9e564957SAndroid Build Coastguard Worker 	dirent->namelen = namelen;
393*9e564957SAndroid Build Coastguard Worker 	dirent->type = (e->attr.st_mode & S_IFMT) >> 12;
394*9e564957SAndroid Build Coastguard Worker 	memcpy(dirent->name, name, namelen);
395*9e564957SAndroid Build Coastguard Worker 	memset(dirent->name + namelen, 0, entlen_padded - entlen);
396*9e564957SAndroid Build Coastguard Worker 
397*9e564957SAndroid Build Coastguard Worker 	return entlen_padded;
398*9e564957SAndroid Build Coastguard Worker }
399*9e564957SAndroid Build Coastguard Worker 
400*9e564957SAndroid Build Coastguard Worker static void fill_open(struct fuse_open_out *arg,
401*9e564957SAndroid Build Coastguard Worker 		      const struct fuse_file_info *f,
402*9e564957SAndroid Build Coastguard Worker 		      int use_upstream_passthrough)
403*9e564957SAndroid Build Coastguard Worker {
404*9e564957SAndroid Build Coastguard Worker 	arg->fh = f->fh;
405*9e564957SAndroid Build Coastguard Worker 	if (use_upstream_passthrough) {
406*9e564957SAndroid Build Coastguard Worker 		if (f->backing_id > 0) {
407*9e564957SAndroid Build Coastguard Worker 			arg->backing_id = f->backing_id;
408*9e564957SAndroid Build Coastguard Worker 			arg->open_flags |= FOPEN_PASSTHROUGH;
409*9e564957SAndroid Build Coastguard Worker 		}
410*9e564957SAndroid Build Coastguard Worker 	} else {
411*9e564957SAndroid Build Coastguard Worker 		arg->passthrough_fh = f->passthrough_fh;
412*9e564957SAndroid Build Coastguard Worker 	}
413*9e564957SAndroid Build Coastguard Worker 
414*9e564957SAndroid Build Coastguard Worker 	if (f->direct_io)
415*9e564957SAndroid Build Coastguard Worker 		arg->open_flags |= FOPEN_DIRECT_IO;
416*9e564957SAndroid Build Coastguard Worker 	if (f->keep_cache)
417*9e564957SAndroid Build Coastguard Worker 		arg->open_flags |= FOPEN_KEEP_CACHE;
418*9e564957SAndroid Build Coastguard Worker 	if (f->cache_readdir)
419*9e564957SAndroid Build Coastguard Worker 		arg->open_flags |= FOPEN_CACHE_DIR;
420*9e564957SAndroid Build Coastguard Worker 	if (f->nonseekable)
421*9e564957SAndroid Build Coastguard Worker 		arg->open_flags |= FOPEN_NONSEEKABLE;
422*9e564957SAndroid Build Coastguard Worker 	if (f->noflush)
423*9e564957SAndroid Build Coastguard Worker 		arg->open_flags |= FOPEN_NOFLUSH;
424*9e564957SAndroid Build Coastguard Worker 	if (f->parallel_direct_writes)
425*9e564957SAndroid Build Coastguard Worker 		arg->open_flags |= FOPEN_PARALLEL_DIRECT_WRITES;
426*9e564957SAndroid Build Coastguard Worker }
427*9e564957SAndroid Build Coastguard Worker 
428*9e564957SAndroid Build Coastguard Worker int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param* e) {
429*9e564957SAndroid Build Coastguard Worker     struct {
430*9e564957SAndroid Build Coastguard Worker         struct fuse_entry_out arg;
431*9e564957SAndroid Build Coastguard Worker         struct fuse_entry_bpf_out bpf_arg;
432*9e564957SAndroid Build Coastguard Worker     } __attribute__((packed)) arg_ext = {0};
433*9e564957SAndroid Build Coastguard Worker 
434*9e564957SAndroid Build Coastguard Worker     struct fuse_entry_out arg;
435*9e564957SAndroid Build Coastguard Worker     struct fuse_entry_bpf_out bpf_arg;
436*9e564957SAndroid Build Coastguard Worker     size_t size;
437*9e564957SAndroid Build Coastguard Worker     int extended_args = e->bpf_action || bpf_arg.bpf_fd || e->backing_action || e->backing_fd;
438*9e564957SAndroid Build Coastguard Worker 
439*9e564957SAndroid Build Coastguard Worker     if (extended_args) {
440*9e564957SAndroid Build Coastguard Worker         size = req->se->conn.proto_minor < 9 ? FUSE_COMPAT_ENTRY_OUT_SIZE : sizeof(arg_ext);
441*9e564957SAndroid Build Coastguard Worker     } else {
442*9e564957SAndroid Build Coastguard Worker         size = req->se->conn.proto_minor < 9 ? FUSE_COMPAT_ENTRY_OUT_SIZE : sizeof(arg);
443*9e564957SAndroid Build Coastguard Worker     }
444*9e564957SAndroid Build Coastguard Worker 
445*9e564957SAndroid Build Coastguard Worker     /* before ABI 7.4 e->ino == 0 was invalid, only ENOENT meant
446*9e564957SAndroid Build Coastguard Worker        negative entry */
447*9e564957SAndroid Build Coastguard Worker     if (!e->ino && req->se->conn.proto_minor < 4) return fuse_reply_err(req, ENOENT);
448*9e564957SAndroid Build Coastguard Worker 
449*9e564957SAndroid Build Coastguard Worker     memset(&arg, 0, sizeof(arg));
450*9e564957SAndroid Build Coastguard Worker     fill_entry(&arg, e);
451*9e564957SAndroid Build Coastguard Worker 
452*9e564957SAndroid Build Coastguard Worker     if (extended_args) {
453*9e564957SAndroid Build Coastguard Worker         memset(&bpf_arg, 0, sizeof(bpf_arg));
454*9e564957SAndroid Build Coastguard Worker 
455*9e564957SAndroid Build Coastguard Worker         bpf_arg.bpf_action = e->bpf_action;
456*9e564957SAndroid Build Coastguard Worker         bpf_arg.bpf_fd = e->bpf_fd;
457*9e564957SAndroid Build Coastguard Worker         bpf_arg.backing_action = e->backing_action;
458*9e564957SAndroid Build Coastguard Worker         bpf_arg.backing_fd = e->backing_fd;
459*9e564957SAndroid Build Coastguard Worker 
460*9e564957SAndroid Build Coastguard Worker         arg_ext.arg = arg;
461*9e564957SAndroid Build Coastguard Worker         arg_ext.bpf_arg = bpf_arg;
462*9e564957SAndroid Build Coastguard Worker 
463*9e564957SAndroid Build Coastguard Worker         return send_reply_ok(req, &arg_ext, size);
464*9e564957SAndroid Build Coastguard Worker     } else {
465*9e564957SAndroid Build Coastguard Worker         return send_reply_ok(req, &arg, size);
466*9e564957SAndroid Build Coastguard Worker     }
467*9e564957SAndroid Build Coastguard Worker }
468*9e564957SAndroid Build Coastguard Worker 
469*9e564957SAndroid Build Coastguard Worker int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e,
470*9e564957SAndroid Build Coastguard Worker 		      const struct fuse_file_info *f)
471*9e564957SAndroid Build Coastguard Worker {
472*9e564957SAndroid Build Coastguard Worker 	char buf[sizeof(struct fuse_entry_out) + sizeof(struct fuse_open_out)];
473*9e564957SAndroid Build Coastguard Worker 	size_t entrysize = req->se->conn.proto_minor < 9 ?
474*9e564957SAndroid Build Coastguard Worker 		FUSE_COMPAT_ENTRY_OUT_SIZE : sizeof(struct fuse_entry_out);
475*9e564957SAndroid Build Coastguard Worker 	struct fuse_entry_out *earg = (struct fuse_entry_out *) buf;
476*9e564957SAndroid Build Coastguard Worker 	struct fuse_open_out *oarg = (struct fuse_open_out *) (buf + entrysize);
477*9e564957SAndroid Build Coastguard Worker 
478*9e564957SAndroid Build Coastguard Worker 	memset(buf, 0, sizeof(buf));
479*9e564957SAndroid Build Coastguard Worker 	fill_entry(earg, e);
480*9e564957SAndroid Build Coastguard Worker 	fill_open(oarg, f, req->se->conn.capable & FUSE_CAP_PASSTHROUGH_UPSTREAM);
481*9e564957SAndroid Build Coastguard Worker 	return send_reply_ok(req, buf,
482*9e564957SAndroid Build Coastguard Worker 			     entrysize + sizeof(struct fuse_open_out));
483*9e564957SAndroid Build Coastguard Worker }
484*9e564957SAndroid Build Coastguard Worker 
485*9e564957SAndroid Build Coastguard Worker int fuse_reply_attr(fuse_req_t req, const struct stat *attr,
486*9e564957SAndroid Build Coastguard Worker 		    double attr_timeout)
487*9e564957SAndroid Build Coastguard Worker {
488*9e564957SAndroid Build Coastguard Worker 	struct fuse_attr_out arg;
489*9e564957SAndroid Build Coastguard Worker 	size_t size = req->se->conn.proto_minor < 9 ?
490*9e564957SAndroid Build Coastguard Worker 		FUSE_COMPAT_ATTR_OUT_SIZE : sizeof(arg);
491*9e564957SAndroid Build Coastguard Worker 
492*9e564957SAndroid Build Coastguard Worker 	memset(&arg, 0, sizeof(arg));
493*9e564957SAndroid Build Coastguard Worker 	arg.attr_valid = calc_timeout_sec(attr_timeout);
494*9e564957SAndroid Build Coastguard Worker 	arg.attr_valid_nsec = calc_timeout_nsec(attr_timeout);
495*9e564957SAndroid Build Coastguard Worker 	convert_stat(attr, &arg.attr);
496*9e564957SAndroid Build Coastguard Worker 
497*9e564957SAndroid Build Coastguard Worker 	return send_reply_ok(req, &arg, size);
498*9e564957SAndroid Build Coastguard Worker }
499*9e564957SAndroid Build Coastguard Worker 
500*9e564957SAndroid Build Coastguard Worker int fuse_reply_readlink(fuse_req_t req, const char *linkname)
501*9e564957SAndroid Build Coastguard Worker {
502*9e564957SAndroid Build Coastguard Worker 	return send_reply_ok(req, linkname, strlen(linkname));
503*9e564957SAndroid Build Coastguard Worker }
504*9e564957SAndroid Build Coastguard Worker 
505*9e564957SAndroid Build Coastguard Worker int fuse_reply_canonical_path(fuse_req_t req, const char *path)
506*9e564957SAndroid Build Coastguard Worker {
507*9e564957SAndroid Build Coastguard Worker 	// The kernel expects a buffer containing the null terminator for this op
508*9e564957SAndroid Build Coastguard Worker 	// So we add the null terminator size to strlen
509*9e564957SAndroid Build Coastguard Worker 	return send_reply_ok(req, path, strlen(path) + 1);
510*9e564957SAndroid Build Coastguard Worker }
511*9e564957SAndroid Build Coastguard Worker 
512*9e564957SAndroid Build Coastguard Worker enum {
513*9e564957SAndroid Build Coastguard Worker 	FUSE_PASSTHROUGH_API_UNAVAILABLE,
514*9e564957SAndroid Build Coastguard Worker 	FUSE_PASSTHROUGH_API_V0,
515*9e564957SAndroid Build Coastguard Worker 	FUSE_PASSTHROUGH_API_V1,
516*9e564957SAndroid Build Coastguard Worker 	FUSE_PASSTHROUGH_API_V2,
517*9e564957SAndroid Build Coastguard Worker 	FUSE_PASSTHROUGH_API_STABLE,
518*9e564957SAndroid Build Coastguard Worker };
519*9e564957SAndroid Build Coastguard Worker 
520*9e564957SAndroid Build Coastguard Worker /*
521*9e564957SAndroid Build Coastguard Worker  * Requests the FUSE passthrough feature to be enabled on a specific file
522*9e564957SAndroid Build Coastguard Worker  * through the passed fd.
523*9e564957SAndroid Build Coastguard Worker  * This function returns an identifier that must be used as passthrough_fh
524*9e564957SAndroid Build Coastguard Worker  * when the open/create_open request reply is sent back to /dev/fuse.
525*9e564957SAndroid Build Coastguard Worker  * As for the current FUSE passthrough implementation, passthrough_fh values
526*9e564957SAndroid Build Coastguard Worker  * are only valid if > 0, so in case the FUSE passthrough open ioctl returns
527*9e564957SAndroid Build Coastguard Worker  * a value <= 0, this must be considered an error and is returned as-is by
528*9e564957SAndroid Build Coastguard Worker  * this function.
529*9e564957SAndroid Build Coastguard Worker  */
530*9e564957SAndroid Build Coastguard Worker int fuse_passthrough_enable(fuse_req_t req, unsigned int fd) {
531*9e564957SAndroid Build Coastguard Worker 	static sig_atomic_t passthrough_version = FUSE_PASSTHROUGH_API_STABLE;
532*9e564957SAndroid Build Coastguard Worker 	int ret = 0; /* values <= 0 represent errors in FUSE passthrough */
533*9e564957SAndroid Build Coastguard Worker 
534*9e564957SAndroid Build Coastguard Worker 	if (!(req->se->conn.capable & FUSE_CAP_PASSTHROUGH))
535*9e564957SAndroid Build Coastguard Worker 		return -ENOTTY;
536*9e564957SAndroid Build Coastguard Worker 	/*
537*9e564957SAndroid Build Coastguard Worker 	 * The interface of FUSE passthrough is still unstable in the kernel,
538*9e564957SAndroid Build Coastguard Worker 	 * so the following solution is to search for the most updated API
539*9e564957SAndroid Build Coastguard Worker 	 * version and, if not found, fall back to an older one.
540*9e564957SAndroid Build Coastguard Worker 	 * This happens when ioctl() returns -1 and errno is set to ENOTTY,
541*9e564957SAndroid Build Coastguard Worker 	 * an error code that corresponds to the lack of a specific ioctl.
542*9e564957SAndroid Build Coastguard Worker 	 */
543*9e564957SAndroid Build Coastguard Worker 	switch (passthrough_version) {
544*9e564957SAndroid Build Coastguard Worker 	case FUSE_PASSTHROUGH_API_STABLE:
545*9e564957SAndroid Build Coastguard Worker 		/* There is not a stable API yet */
546*9e564957SAndroid Build Coastguard Worker 		passthrough_version = FUSE_PASSTHROUGH_API_V2;
547*9e564957SAndroid Build Coastguard Worker 	case FUSE_PASSTHROUGH_API_V2: {
548*9e564957SAndroid Build Coastguard Worker 		ret = ioctl(req->se->fd, FUSE_DEV_IOC_PASSTHROUGH_OPEN_V2, &fd);
549*9e564957SAndroid Build Coastguard Worker 		if (ret == -1 && errno == ENOTTY)
550*9e564957SAndroid Build Coastguard Worker 			passthrough_version = FUSE_PASSTHROUGH_API_V1;
551*9e564957SAndroid Build Coastguard Worker 		else
552*9e564957SAndroid Build Coastguard Worker 			break;
553*9e564957SAndroid Build Coastguard Worker 	}
554*9e564957SAndroid Build Coastguard Worker 	case FUSE_PASSTHROUGH_API_V1: {
555*9e564957SAndroid Build Coastguard Worker 		struct fuse_passthrough_out_v0 out = {};
556*9e564957SAndroid Build Coastguard Worker 		out.fd = fd;
557*9e564957SAndroid Build Coastguard Worker 
558*9e564957SAndroid Build Coastguard Worker 		ret = ioctl(req->se->fd, FUSE_DEV_IOC_PASSTHROUGH_OPEN_V1, &out);
559*9e564957SAndroid Build Coastguard Worker 		if (ret == -1 && errno == ENOTTY)
560*9e564957SAndroid Build Coastguard Worker 			passthrough_version = FUSE_PASSTHROUGH_API_V0;
561*9e564957SAndroid Build Coastguard Worker 		else
562*9e564957SAndroid Build Coastguard Worker 			break;
563*9e564957SAndroid Build Coastguard Worker 	}
564*9e564957SAndroid Build Coastguard Worker 	case FUSE_PASSTHROUGH_API_V0: {
565*9e564957SAndroid Build Coastguard Worker 		struct fuse_passthrough_out_v0 out = {};
566*9e564957SAndroid Build Coastguard Worker 		out.fd = fd;
567*9e564957SAndroid Build Coastguard Worker 
568*9e564957SAndroid Build Coastguard Worker 		ret = ioctl(req->se->fd, FUSE_DEV_IOC_PASSTHROUGH_OPEN_V0, &out);
569*9e564957SAndroid Build Coastguard Worker 		if (ret == -1 && errno == ENOTTY)
570*9e564957SAndroid Build Coastguard Worker 			passthrough_version = FUSE_PASSTHROUGH_API_UNAVAILABLE;
571*9e564957SAndroid Build Coastguard Worker 		else
572*9e564957SAndroid Build Coastguard Worker 			break;
573*9e564957SAndroid Build Coastguard Worker 	}
574*9e564957SAndroid Build Coastguard Worker 	default:
575*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: passthrough_enable no valid API\n");
576*9e564957SAndroid Build Coastguard Worker 		return -ENOTTY;
577*9e564957SAndroid Build Coastguard Worker 	}
578*9e564957SAndroid Build Coastguard Worker 
579*9e564957SAndroid Build Coastguard Worker 	if (ret <= 0)
580*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: passthrough_enable: %s\n", strerror(errno));
581*9e564957SAndroid Build Coastguard Worker 	return ret;
582*9e564957SAndroid Build Coastguard Worker }
583*9e564957SAndroid Build Coastguard Worker 
584*9e564957SAndroid Build Coastguard Worker int fuse_passthrough_open(fuse_req_t req, int fd)
585*9e564957SAndroid Build Coastguard Worker {
586*9e564957SAndroid Build Coastguard Worker 	struct fuse_backing_map map = { .fd = fd };
587*9e564957SAndroid Build Coastguard Worker 	int ret;
588*9e564957SAndroid Build Coastguard Worker 
589*9e564957SAndroid Build Coastguard Worker 	ret = ioctl(req->se->fd, FUSE_DEV_IOC_BACKING_OPEN, &map);
590*9e564957SAndroid Build Coastguard Worker 	if (ret <= 0) {
591*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: passthrough_open: %s\n", strerror(errno));
592*9e564957SAndroid Build Coastguard Worker 		return 0;
593*9e564957SAndroid Build Coastguard Worker 	}
594*9e564957SAndroid Build Coastguard Worker 
595*9e564957SAndroid Build Coastguard Worker 	return ret;
596*9e564957SAndroid Build Coastguard Worker }
597*9e564957SAndroid Build Coastguard Worker 
598*9e564957SAndroid Build Coastguard Worker int fuse_passthrough_close(fuse_req_t req, int backing_id)
599*9e564957SAndroid Build Coastguard Worker {
600*9e564957SAndroid Build Coastguard Worker 	int ret;
601*9e564957SAndroid Build Coastguard Worker 
602*9e564957SAndroid Build Coastguard Worker 	ret = ioctl(req->se->fd, FUSE_DEV_IOC_BACKING_CLOSE, &backing_id);
603*9e564957SAndroid Build Coastguard Worker 	if (ret < 0)
604*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: passthrough_close: %s\n", strerror(errno));
605*9e564957SAndroid Build Coastguard Worker 
606*9e564957SAndroid Build Coastguard Worker 	return ret;
607*9e564957SAndroid Build Coastguard Worker }
608*9e564957SAndroid Build Coastguard Worker 
609*9e564957SAndroid Build Coastguard Worker int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *f)
610*9e564957SAndroid Build Coastguard Worker {
611*9e564957SAndroid Build Coastguard Worker 	struct fuse_open_out arg;
612*9e564957SAndroid Build Coastguard Worker 
613*9e564957SAndroid Build Coastguard Worker 	memset(&arg, 0, sizeof(arg));
614*9e564957SAndroid Build Coastguard Worker 	fill_open(&arg, f, req->se->conn.capable & FUSE_CAP_PASSTHROUGH_UPSTREAM);
615*9e564957SAndroid Build Coastguard Worker 	return send_reply_ok(req, &arg, sizeof(arg));
616*9e564957SAndroid Build Coastguard Worker }
617*9e564957SAndroid Build Coastguard Worker 
618*9e564957SAndroid Build Coastguard Worker int fuse_reply_write(fuse_req_t req, size_t count)
619*9e564957SAndroid Build Coastguard Worker {
620*9e564957SAndroid Build Coastguard Worker 	struct fuse_write_out arg;
621*9e564957SAndroid Build Coastguard Worker 
622*9e564957SAndroid Build Coastguard Worker 	memset(&arg, 0, sizeof(arg));
623*9e564957SAndroid Build Coastguard Worker 	arg.size = count;
624*9e564957SAndroid Build Coastguard Worker 
625*9e564957SAndroid Build Coastguard Worker 	return send_reply_ok(req, &arg, sizeof(arg));
626*9e564957SAndroid Build Coastguard Worker }
627*9e564957SAndroid Build Coastguard Worker 
628*9e564957SAndroid Build Coastguard Worker int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size)
629*9e564957SAndroid Build Coastguard Worker {
630*9e564957SAndroid Build Coastguard Worker 	return send_reply_ok(req, buf, size);
631*9e564957SAndroid Build Coastguard Worker }
632*9e564957SAndroid Build Coastguard Worker 
633*9e564957SAndroid Build Coastguard Worker static int fuse_send_data_iov_fallback(struct fuse_session *se,
634*9e564957SAndroid Build Coastguard Worker 				       struct fuse_chan *ch,
635*9e564957SAndroid Build Coastguard Worker 				       struct iovec *iov, int iov_count,
636*9e564957SAndroid Build Coastguard Worker 				       struct fuse_bufvec *buf,
637*9e564957SAndroid Build Coastguard Worker 				       size_t len)
638*9e564957SAndroid Build Coastguard Worker {
639*9e564957SAndroid Build Coastguard Worker 	struct fuse_bufvec mem_buf = FUSE_BUFVEC_INIT(len);
640*9e564957SAndroid Build Coastguard Worker 	void *mbuf;
641*9e564957SAndroid Build Coastguard Worker 	int res;
642*9e564957SAndroid Build Coastguard Worker 
643*9e564957SAndroid Build Coastguard Worker 	/* Optimize common case */
644*9e564957SAndroid Build Coastguard Worker 	if (buf->count == 1 && buf->idx == 0 && buf->off == 0 &&
645*9e564957SAndroid Build Coastguard Worker 	    !(buf->buf[0].flags & FUSE_BUF_IS_FD)) {
646*9e564957SAndroid Build Coastguard Worker 		/* FIXME: also avoid memory copy if there are multiple buffers
647*9e564957SAndroid Build Coastguard Worker 		   but none of them contain an fd */
648*9e564957SAndroid Build Coastguard Worker 
649*9e564957SAndroid Build Coastguard Worker 		iov[iov_count].iov_base = buf->buf[0].mem;
650*9e564957SAndroid Build Coastguard Worker 		iov[iov_count].iov_len = len;
651*9e564957SAndroid Build Coastguard Worker 		iov_count++;
652*9e564957SAndroid Build Coastguard Worker 		return fuse_send_msg(se, ch, iov, iov_count);
653*9e564957SAndroid Build Coastguard Worker 	}
654*9e564957SAndroid Build Coastguard Worker 
655*9e564957SAndroid Build Coastguard Worker 	res = posix_memalign(&mbuf, pagesize, len);
656*9e564957SAndroid Build Coastguard Worker 	if (res != 0)
657*9e564957SAndroid Build Coastguard Worker 		return res;
658*9e564957SAndroid Build Coastguard Worker 
659*9e564957SAndroid Build Coastguard Worker 	mem_buf.buf[0].mem = mbuf;
660*9e564957SAndroid Build Coastguard Worker 	res = fuse_buf_copy(&mem_buf, buf, 0);
661*9e564957SAndroid Build Coastguard Worker 	if (res < 0) {
662*9e564957SAndroid Build Coastguard Worker 		free(mbuf);
663*9e564957SAndroid Build Coastguard Worker 		return -res;
664*9e564957SAndroid Build Coastguard Worker 	}
665*9e564957SAndroid Build Coastguard Worker 	len = res;
666*9e564957SAndroid Build Coastguard Worker 
667*9e564957SAndroid Build Coastguard Worker 	iov[iov_count].iov_base = mbuf;
668*9e564957SAndroid Build Coastguard Worker 	iov[iov_count].iov_len = len;
669*9e564957SAndroid Build Coastguard Worker 	iov_count++;
670*9e564957SAndroid Build Coastguard Worker 	res = fuse_send_msg(se, ch, iov, iov_count);
671*9e564957SAndroid Build Coastguard Worker 	free(mbuf);
672*9e564957SAndroid Build Coastguard Worker 
673*9e564957SAndroid Build Coastguard Worker 	return res;
674*9e564957SAndroid Build Coastguard Worker }
675*9e564957SAndroid Build Coastguard Worker 
676*9e564957SAndroid Build Coastguard Worker struct fuse_ll_pipe {
677*9e564957SAndroid Build Coastguard Worker 	size_t size;
678*9e564957SAndroid Build Coastguard Worker 	int can_grow;
679*9e564957SAndroid Build Coastguard Worker 	int pipe[2];
680*9e564957SAndroid Build Coastguard Worker };
681*9e564957SAndroid Build Coastguard Worker 
682*9e564957SAndroid Build Coastguard Worker static void fuse_ll_pipe_free(struct fuse_ll_pipe *llp)
683*9e564957SAndroid Build Coastguard Worker {
684*9e564957SAndroid Build Coastguard Worker 	close(llp->pipe[0]);
685*9e564957SAndroid Build Coastguard Worker 	close(llp->pipe[1]);
686*9e564957SAndroid Build Coastguard Worker 	free(llp);
687*9e564957SAndroid Build Coastguard Worker }
688*9e564957SAndroid Build Coastguard Worker 
689*9e564957SAndroid Build Coastguard Worker #ifdef HAVE_SPLICE
690*9e564957SAndroid Build Coastguard Worker #if !defined(HAVE_PIPE2) || !defined(O_CLOEXEC)
691*9e564957SAndroid Build Coastguard Worker static int fuse_pipe(int fds[2])
692*9e564957SAndroid Build Coastguard Worker {
693*9e564957SAndroid Build Coastguard Worker 	int rv = pipe(fds);
694*9e564957SAndroid Build Coastguard Worker 
695*9e564957SAndroid Build Coastguard Worker 	if (rv == -1)
696*9e564957SAndroid Build Coastguard Worker 		return rv;
697*9e564957SAndroid Build Coastguard Worker 
698*9e564957SAndroid Build Coastguard Worker 	if (fcntl(fds[0], F_SETFL, O_NONBLOCK) == -1 ||
699*9e564957SAndroid Build Coastguard Worker 	    fcntl(fds[1], F_SETFL, O_NONBLOCK) == -1 ||
700*9e564957SAndroid Build Coastguard Worker 	    fcntl(fds[0], F_SETFD, FD_CLOEXEC) == -1 ||
701*9e564957SAndroid Build Coastguard Worker 	    fcntl(fds[1], F_SETFD, FD_CLOEXEC) == -1) {
702*9e564957SAndroid Build Coastguard Worker 		close(fds[0]);
703*9e564957SAndroid Build Coastguard Worker 		close(fds[1]);
704*9e564957SAndroid Build Coastguard Worker 		rv = -1;
705*9e564957SAndroid Build Coastguard Worker 	}
706*9e564957SAndroid Build Coastguard Worker 	return rv;
707*9e564957SAndroid Build Coastguard Worker }
708*9e564957SAndroid Build Coastguard Worker #else
709*9e564957SAndroid Build Coastguard Worker static int fuse_pipe(int fds[2])
710*9e564957SAndroid Build Coastguard Worker {
711*9e564957SAndroid Build Coastguard Worker 	return pipe2(fds, O_CLOEXEC | O_NONBLOCK);
712*9e564957SAndroid Build Coastguard Worker }
713*9e564957SAndroid Build Coastguard Worker #endif
714*9e564957SAndroid Build Coastguard Worker 
715*9e564957SAndroid Build Coastguard Worker static struct fuse_ll_pipe *fuse_ll_get_pipe(struct fuse_session *se)
716*9e564957SAndroid Build Coastguard Worker {
717*9e564957SAndroid Build Coastguard Worker 	struct fuse_ll_pipe *llp = pthread_getspecific(se->pipe_key);
718*9e564957SAndroid Build Coastguard Worker 	if (llp == NULL) {
719*9e564957SAndroid Build Coastguard Worker 		int res;
720*9e564957SAndroid Build Coastguard Worker 
721*9e564957SAndroid Build Coastguard Worker 		llp = malloc(sizeof(struct fuse_ll_pipe));
722*9e564957SAndroid Build Coastguard Worker 		if (llp == NULL)
723*9e564957SAndroid Build Coastguard Worker 			return NULL;
724*9e564957SAndroid Build Coastguard Worker 
725*9e564957SAndroid Build Coastguard Worker 		res = fuse_pipe(llp->pipe);
726*9e564957SAndroid Build Coastguard Worker 		if (res == -1) {
727*9e564957SAndroid Build Coastguard Worker 			free(llp);
728*9e564957SAndroid Build Coastguard Worker 			return NULL;
729*9e564957SAndroid Build Coastguard Worker 		}
730*9e564957SAndroid Build Coastguard Worker 
731*9e564957SAndroid Build Coastguard Worker 		/*
732*9e564957SAndroid Build Coastguard Worker 		 *the default size is 16 pages on linux
733*9e564957SAndroid Build Coastguard Worker 		 */
734*9e564957SAndroid Build Coastguard Worker 		llp->size = pagesize * 16;
735*9e564957SAndroid Build Coastguard Worker 		llp->can_grow = 1;
736*9e564957SAndroid Build Coastguard Worker 
737*9e564957SAndroid Build Coastguard Worker 		pthread_setspecific(se->pipe_key, llp);
738*9e564957SAndroid Build Coastguard Worker 	}
739*9e564957SAndroid Build Coastguard Worker 
740*9e564957SAndroid Build Coastguard Worker 	return llp;
741*9e564957SAndroid Build Coastguard Worker }
742*9e564957SAndroid Build Coastguard Worker #endif
743*9e564957SAndroid Build Coastguard Worker 
744*9e564957SAndroid Build Coastguard Worker static void fuse_ll_clear_pipe(struct fuse_session *se)
745*9e564957SAndroid Build Coastguard Worker {
746*9e564957SAndroid Build Coastguard Worker 	struct fuse_ll_pipe *llp = pthread_getspecific(se->pipe_key);
747*9e564957SAndroid Build Coastguard Worker 	if (llp) {
748*9e564957SAndroid Build Coastguard Worker 		pthread_setspecific(se->pipe_key, NULL);
749*9e564957SAndroid Build Coastguard Worker 		fuse_ll_pipe_free(llp);
750*9e564957SAndroid Build Coastguard Worker 	}
751*9e564957SAndroid Build Coastguard Worker }
752*9e564957SAndroid Build Coastguard Worker 
753*9e564957SAndroid Build Coastguard Worker #if defined(HAVE_SPLICE) && defined(HAVE_VMSPLICE)
754*9e564957SAndroid Build Coastguard Worker static int read_back(int fd, char *buf, size_t len)
755*9e564957SAndroid Build Coastguard Worker {
756*9e564957SAndroid Build Coastguard Worker 	int res;
757*9e564957SAndroid Build Coastguard Worker 
758*9e564957SAndroid Build Coastguard Worker 	res = read(fd, buf, len);
759*9e564957SAndroid Build Coastguard Worker 	if (res == -1) {
760*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: internal error: failed to read back from pipe: %s\n", strerror(errno));
761*9e564957SAndroid Build Coastguard Worker 		return -EIO;
762*9e564957SAndroid Build Coastguard Worker 	}
763*9e564957SAndroid Build Coastguard Worker 	if (res != len) {
764*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: internal error: short read back from pipe: %i from %zi\n", res, len);
765*9e564957SAndroid Build Coastguard Worker 		return -EIO;
766*9e564957SAndroid Build Coastguard Worker 	}
767*9e564957SAndroid Build Coastguard Worker 	return 0;
768*9e564957SAndroid Build Coastguard Worker }
769*9e564957SAndroid Build Coastguard Worker 
770*9e564957SAndroid Build Coastguard Worker static int grow_pipe_to_max(int pipefd)
771*9e564957SAndroid Build Coastguard Worker {
772*9e564957SAndroid Build Coastguard Worker 	int max;
773*9e564957SAndroid Build Coastguard Worker 	int res;
774*9e564957SAndroid Build Coastguard Worker 	int maxfd;
775*9e564957SAndroid Build Coastguard Worker 	char buf[32];
776*9e564957SAndroid Build Coastguard Worker 
777*9e564957SAndroid Build Coastguard Worker 	maxfd = open("/proc/sys/fs/pipe-max-size", O_RDONLY);
778*9e564957SAndroid Build Coastguard Worker 	if (maxfd < 0)
779*9e564957SAndroid Build Coastguard Worker 		return -errno;
780*9e564957SAndroid Build Coastguard Worker 
781*9e564957SAndroid Build Coastguard Worker 	res = read(maxfd, buf, sizeof(buf) - 1);
782*9e564957SAndroid Build Coastguard Worker 	if (res < 0) {
783*9e564957SAndroid Build Coastguard Worker 		int saved_errno;
784*9e564957SAndroid Build Coastguard Worker 
785*9e564957SAndroid Build Coastguard Worker 		saved_errno = errno;
786*9e564957SAndroid Build Coastguard Worker 		close(maxfd);
787*9e564957SAndroid Build Coastguard Worker 		return -saved_errno;
788*9e564957SAndroid Build Coastguard Worker 	}
789*9e564957SAndroid Build Coastguard Worker 	close(maxfd);
790*9e564957SAndroid Build Coastguard Worker 	buf[res] = '\0';
791*9e564957SAndroid Build Coastguard Worker 
792*9e564957SAndroid Build Coastguard Worker 	max = atoi(buf);
793*9e564957SAndroid Build Coastguard Worker 	res = fcntl(pipefd, F_SETPIPE_SZ, max);
794*9e564957SAndroid Build Coastguard Worker 	if (res < 0)
795*9e564957SAndroid Build Coastguard Worker 		return -errno;
796*9e564957SAndroid Build Coastguard Worker 	return max;
797*9e564957SAndroid Build Coastguard Worker }
798*9e564957SAndroid Build Coastguard Worker 
799*9e564957SAndroid Build Coastguard Worker static int fuse_send_data_iov(struct fuse_session *se, struct fuse_chan *ch,
800*9e564957SAndroid Build Coastguard Worker 			       struct iovec *iov, int iov_count,
801*9e564957SAndroid Build Coastguard Worker 			       struct fuse_bufvec *buf, unsigned int flags)
802*9e564957SAndroid Build Coastguard Worker {
803*9e564957SAndroid Build Coastguard Worker 	int res;
804*9e564957SAndroid Build Coastguard Worker 	size_t len = fuse_buf_size(buf);
805*9e564957SAndroid Build Coastguard Worker 	struct fuse_out_header *out = iov[0].iov_base;
806*9e564957SAndroid Build Coastguard Worker 	struct fuse_ll_pipe *llp;
807*9e564957SAndroid Build Coastguard Worker 	int splice_flags;
808*9e564957SAndroid Build Coastguard Worker 	size_t pipesize;
809*9e564957SAndroid Build Coastguard Worker 	size_t total_buf_size;
810*9e564957SAndroid Build Coastguard Worker 	size_t idx;
811*9e564957SAndroid Build Coastguard Worker 	size_t headerlen;
812*9e564957SAndroid Build Coastguard Worker 	struct fuse_bufvec pipe_buf = FUSE_BUFVEC_INIT(len);
813*9e564957SAndroid Build Coastguard Worker 
814*9e564957SAndroid Build Coastguard Worker 	if (se->broken_splice_nonblock)
815*9e564957SAndroid Build Coastguard Worker 		goto fallback;
816*9e564957SAndroid Build Coastguard Worker 
817*9e564957SAndroid Build Coastguard Worker 	if (flags & FUSE_BUF_NO_SPLICE)
818*9e564957SAndroid Build Coastguard Worker 		goto fallback;
819*9e564957SAndroid Build Coastguard Worker 
820*9e564957SAndroid Build Coastguard Worker 	total_buf_size = 0;
821*9e564957SAndroid Build Coastguard Worker 	for (idx = buf->idx; idx < buf->count; idx++) {
822*9e564957SAndroid Build Coastguard Worker 		total_buf_size += buf->buf[idx].size;
823*9e564957SAndroid Build Coastguard Worker 		if (idx == buf->idx)
824*9e564957SAndroid Build Coastguard Worker 			total_buf_size -= buf->off;
825*9e564957SAndroid Build Coastguard Worker 	}
826*9e564957SAndroid Build Coastguard Worker 	if (total_buf_size < 2 * pagesize)
827*9e564957SAndroid Build Coastguard Worker 		goto fallback;
828*9e564957SAndroid Build Coastguard Worker 
829*9e564957SAndroid Build Coastguard Worker 	if (se->conn.proto_minor < 14 ||
830*9e564957SAndroid Build Coastguard Worker 	    !(se->conn.want & FUSE_CAP_SPLICE_WRITE))
831*9e564957SAndroid Build Coastguard Worker 		goto fallback;
832*9e564957SAndroid Build Coastguard Worker 
833*9e564957SAndroid Build Coastguard Worker 	llp = fuse_ll_get_pipe(se);
834*9e564957SAndroid Build Coastguard Worker 	if (llp == NULL)
835*9e564957SAndroid Build Coastguard Worker 		goto fallback;
836*9e564957SAndroid Build Coastguard Worker 
837*9e564957SAndroid Build Coastguard Worker 
838*9e564957SAndroid Build Coastguard Worker 	headerlen = iov_length(iov, iov_count);
839*9e564957SAndroid Build Coastguard Worker 
840*9e564957SAndroid Build Coastguard Worker 	out->len = headerlen + len;
841*9e564957SAndroid Build Coastguard Worker 
842*9e564957SAndroid Build Coastguard Worker 	/*
843*9e564957SAndroid Build Coastguard Worker 	 * Heuristic for the required pipe size, does not work if the
844*9e564957SAndroid Build Coastguard Worker 	 * source contains less than page size fragments
845*9e564957SAndroid Build Coastguard Worker 	 */
846*9e564957SAndroid Build Coastguard Worker 	pipesize = pagesize * (iov_count + buf->count + 1) + out->len;
847*9e564957SAndroid Build Coastguard Worker 
848*9e564957SAndroid Build Coastguard Worker 	if (llp->size < pipesize) {
849*9e564957SAndroid Build Coastguard Worker 		if (llp->can_grow) {
850*9e564957SAndroid Build Coastguard Worker 			res = fcntl(llp->pipe[0], F_SETPIPE_SZ, pipesize);
851*9e564957SAndroid Build Coastguard Worker 			if (res == -1) {
852*9e564957SAndroid Build Coastguard Worker 				res = grow_pipe_to_max(llp->pipe[0]);
853*9e564957SAndroid Build Coastguard Worker 				if (res > 0)
854*9e564957SAndroid Build Coastguard Worker 					llp->size = res;
855*9e564957SAndroid Build Coastguard Worker 				llp->can_grow = 0;
856*9e564957SAndroid Build Coastguard Worker 				goto fallback;
857*9e564957SAndroid Build Coastguard Worker 			}
858*9e564957SAndroid Build Coastguard Worker 			llp->size = res;
859*9e564957SAndroid Build Coastguard Worker 		}
860*9e564957SAndroid Build Coastguard Worker 		if (llp->size < pipesize)
861*9e564957SAndroid Build Coastguard Worker 			goto fallback;
862*9e564957SAndroid Build Coastguard Worker 	}
863*9e564957SAndroid Build Coastguard Worker 
864*9e564957SAndroid Build Coastguard Worker 
865*9e564957SAndroid Build Coastguard Worker 	res = vmsplice(llp->pipe[1], iov, iov_count, SPLICE_F_NONBLOCK);
866*9e564957SAndroid Build Coastguard Worker 	if (res == -1)
867*9e564957SAndroid Build Coastguard Worker 		goto fallback;
868*9e564957SAndroid Build Coastguard Worker 
869*9e564957SAndroid Build Coastguard Worker 	if (res != headerlen) {
870*9e564957SAndroid Build Coastguard Worker 		res = -EIO;
871*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: short vmsplice to pipe: %u/%zu\n", res,
872*9e564957SAndroid Build Coastguard Worker 			headerlen);
873*9e564957SAndroid Build Coastguard Worker 		goto clear_pipe;
874*9e564957SAndroid Build Coastguard Worker 	}
875*9e564957SAndroid Build Coastguard Worker 
876*9e564957SAndroid Build Coastguard Worker 	pipe_buf.buf[0].flags = FUSE_BUF_IS_FD;
877*9e564957SAndroid Build Coastguard Worker 	pipe_buf.buf[0].fd = llp->pipe[1];
878*9e564957SAndroid Build Coastguard Worker 
879*9e564957SAndroid Build Coastguard Worker 	res = fuse_buf_copy(&pipe_buf, buf,
880*9e564957SAndroid Build Coastguard Worker 			    FUSE_BUF_FORCE_SPLICE | FUSE_BUF_SPLICE_NONBLOCK);
881*9e564957SAndroid Build Coastguard Worker 	if (res < 0) {
882*9e564957SAndroid Build Coastguard Worker 		if (res == -EAGAIN || res == -EINVAL) {
883*9e564957SAndroid Build Coastguard Worker 			/*
884*9e564957SAndroid Build Coastguard Worker 			 * Should only get EAGAIN on kernels with
885*9e564957SAndroid Build Coastguard Worker 			 * broken SPLICE_F_NONBLOCK support (<=
886*9e564957SAndroid Build Coastguard Worker 			 * 2.6.35) where this error or a short read is
887*9e564957SAndroid Build Coastguard Worker 			 * returned even if the pipe itself is not
888*9e564957SAndroid Build Coastguard Worker 			 * full
889*9e564957SAndroid Build Coastguard Worker 			 *
890*9e564957SAndroid Build Coastguard Worker 			 * EINVAL might mean that splice can't handle
891*9e564957SAndroid Build Coastguard Worker 			 * this combination of input and output.
892*9e564957SAndroid Build Coastguard Worker 			 */
893*9e564957SAndroid Build Coastguard Worker 			if (res == -EAGAIN)
894*9e564957SAndroid Build Coastguard Worker 				se->broken_splice_nonblock = 1;
895*9e564957SAndroid Build Coastguard Worker 
896*9e564957SAndroid Build Coastguard Worker 			pthread_setspecific(se->pipe_key, NULL);
897*9e564957SAndroid Build Coastguard Worker 			fuse_ll_pipe_free(llp);
898*9e564957SAndroid Build Coastguard Worker 			goto fallback;
899*9e564957SAndroid Build Coastguard Worker 		}
900*9e564957SAndroid Build Coastguard Worker 		res = -res;
901*9e564957SAndroid Build Coastguard Worker 		goto clear_pipe;
902*9e564957SAndroid Build Coastguard Worker 	}
903*9e564957SAndroid Build Coastguard Worker 
904*9e564957SAndroid Build Coastguard Worker 	if (res != 0 && res < len) {
905*9e564957SAndroid Build Coastguard Worker 		struct fuse_bufvec mem_buf = FUSE_BUFVEC_INIT(len);
906*9e564957SAndroid Build Coastguard Worker 		void *mbuf;
907*9e564957SAndroid Build Coastguard Worker 		size_t now_len = res;
908*9e564957SAndroid Build Coastguard Worker 		/*
909*9e564957SAndroid Build Coastguard Worker 		 * For regular files a short count is either
910*9e564957SAndroid Build Coastguard Worker 		 *  1) due to EOF, or
911*9e564957SAndroid Build Coastguard Worker 		 *  2) because of broken SPLICE_F_NONBLOCK (see above)
912*9e564957SAndroid Build Coastguard Worker 		 *
913*9e564957SAndroid Build Coastguard Worker 		 * For other inputs it's possible that we overflowed
914*9e564957SAndroid Build Coastguard Worker 		 * the pipe because of small buffer fragments.
915*9e564957SAndroid Build Coastguard Worker 		 */
916*9e564957SAndroid Build Coastguard Worker 
917*9e564957SAndroid Build Coastguard Worker 		res = posix_memalign(&mbuf, pagesize, len);
918*9e564957SAndroid Build Coastguard Worker 		if (res != 0)
919*9e564957SAndroid Build Coastguard Worker 			goto clear_pipe;
920*9e564957SAndroid Build Coastguard Worker 
921*9e564957SAndroid Build Coastguard Worker 		mem_buf.buf[0].mem = mbuf;
922*9e564957SAndroid Build Coastguard Worker 		mem_buf.off = now_len;
923*9e564957SAndroid Build Coastguard Worker 		res = fuse_buf_copy(&mem_buf, buf, 0);
924*9e564957SAndroid Build Coastguard Worker 		if (res > 0) {
925*9e564957SAndroid Build Coastguard Worker 			char *tmpbuf;
926*9e564957SAndroid Build Coastguard Worker 			size_t extra_len = res;
927*9e564957SAndroid Build Coastguard Worker 			/*
928*9e564957SAndroid Build Coastguard Worker 			 * Trickiest case: got more data.  Need to get
929*9e564957SAndroid Build Coastguard Worker 			 * back the data from the pipe and then fall
930*9e564957SAndroid Build Coastguard Worker 			 * back to regular write.
931*9e564957SAndroid Build Coastguard Worker 			 */
932*9e564957SAndroid Build Coastguard Worker 			tmpbuf = malloc(headerlen);
933*9e564957SAndroid Build Coastguard Worker 			if (tmpbuf == NULL) {
934*9e564957SAndroid Build Coastguard Worker 				free(mbuf);
935*9e564957SAndroid Build Coastguard Worker 				res = ENOMEM;
936*9e564957SAndroid Build Coastguard Worker 				goto clear_pipe;
937*9e564957SAndroid Build Coastguard Worker 			}
938*9e564957SAndroid Build Coastguard Worker 			res = read_back(llp->pipe[0], tmpbuf, headerlen);
939*9e564957SAndroid Build Coastguard Worker 			free(tmpbuf);
940*9e564957SAndroid Build Coastguard Worker 			if (res != 0) {
941*9e564957SAndroid Build Coastguard Worker 				free(mbuf);
942*9e564957SAndroid Build Coastguard Worker 				goto clear_pipe;
943*9e564957SAndroid Build Coastguard Worker 			}
944*9e564957SAndroid Build Coastguard Worker 			res = read_back(llp->pipe[0], mbuf, now_len);
945*9e564957SAndroid Build Coastguard Worker 			if (res != 0) {
946*9e564957SAndroid Build Coastguard Worker 				free(mbuf);
947*9e564957SAndroid Build Coastguard Worker 				goto clear_pipe;
948*9e564957SAndroid Build Coastguard Worker 			}
949*9e564957SAndroid Build Coastguard Worker 			len = now_len + extra_len;
950*9e564957SAndroid Build Coastguard Worker 			iov[iov_count].iov_base = mbuf;
951*9e564957SAndroid Build Coastguard Worker 			iov[iov_count].iov_len = len;
952*9e564957SAndroid Build Coastguard Worker 			iov_count++;
953*9e564957SAndroid Build Coastguard Worker 			res = fuse_send_msg(se, ch, iov, iov_count);
954*9e564957SAndroid Build Coastguard Worker 			free(mbuf);
955*9e564957SAndroid Build Coastguard Worker 			return res;
956*9e564957SAndroid Build Coastguard Worker 		}
957*9e564957SAndroid Build Coastguard Worker 		free(mbuf);
958*9e564957SAndroid Build Coastguard Worker 		res = now_len;
959*9e564957SAndroid Build Coastguard Worker 	}
960*9e564957SAndroid Build Coastguard Worker 	len = res;
961*9e564957SAndroid Build Coastguard Worker 	out->len = headerlen + len;
962*9e564957SAndroid Build Coastguard Worker 
963*9e564957SAndroid Build Coastguard Worker 	if (se->debug) {
964*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_DEBUG,
965*9e564957SAndroid Build Coastguard Worker 			"   unique: %llu, success, outsize: %i (splice)\n",
966*9e564957SAndroid Build Coastguard Worker 			(unsigned long long) out->unique, out->len);
967*9e564957SAndroid Build Coastguard Worker 	}
968*9e564957SAndroid Build Coastguard Worker 
969*9e564957SAndroid Build Coastguard Worker 	splice_flags = 0;
970*9e564957SAndroid Build Coastguard Worker 	if ((flags & FUSE_BUF_SPLICE_MOVE) &&
971*9e564957SAndroid Build Coastguard Worker 	    (se->conn.want & FUSE_CAP_SPLICE_MOVE))
972*9e564957SAndroid Build Coastguard Worker 		splice_flags |= SPLICE_F_MOVE;
973*9e564957SAndroid Build Coastguard Worker 
974*9e564957SAndroid Build Coastguard Worker 	if (se->io != NULL && se->io->splice_send != NULL) {
975*9e564957SAndroid Build Coastguard Worker 		res = se->io->splice_send(llp->pipe[0], NULL,
976*9e564957SAndroid Build Coastguard Worker 						  ch ? ch->fd : se->fd, NULL, out->len,
977*9e564957SAndroid Build Coastguard Worker 					  	  splice_flags, se->userdata);
978*9e564957SAndroid Build Coastguard Worker 	} else {
979*9e564957SAndroid Build Coastguard Worker 		res = splice(llp->pipe[0], NULL, ch ? ch->fd : se->fd, NULL,
980*9e564957SAndroid Build Coastguard Worker 			       out->len, splice_flags);
981*9e564957SAndroid Build Coastguard Worker 	}
982*9e564957SAndroid Build Coastguard Worker 	if (res == -1) {
983*9e564957SAndroid Build Coastguard Worker 		res = -errno;
984*9e564957SAndroid Build Coastguard Worker 		perror("fuse: splice from pipe");
985*9e564957SAndroid Build Coastguard Worker 		goto clear_pipe;
986*9e564957SAndroid Build Coastguard Worker 	}
987*9e564957SAndroid Build Coastguard Worker 	if (res != out->len) {
988*9e564957SAndroid Build Coastguard Worker 		res = -EIO;
989*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: short splice from pipe: %u/%u\n",
990*9e564957SAndroid Build Coastguard Worker 			res, out->len);
991*9e564957SAndroid Build Coastguard Worker 		goto clear_pipe;
992*9e564957SAndroid Build Coastguard Worker 	}
993*9e564957SAndroid Build Coastguard Worker 	return 0;
994*9e564957SAndroid Build Coastguard Worker 
995*9e564957SAndroid Build Coastguard Worker clear_pipe:
996*9e564957SAndroid Build Coastguard Worker 	fuse_ll_clear_pipe(se);
997*9e564957SAndroid Build Coastguard Worker 	return res;
998*9e564957SAndroid Build Coastguard Worker 
999*9e564957SAndroid Build Coastguard Worker fallback:
1000*9e564957SAndroid Build Coastguard Worker 	return fuse_send_data_iov_fallback(se, ch, iov, iov_count, buf, len);
1001*9e564957SAndroid Build Coastguard Worker }
1002*9e564957SAndroid Build Coastguard Worker #else
1003*9e564957SAndroid Build Coastguard Worker static int fuse_send_data_iov(struct fuse_session *se, struct fuse_chan *ch,
1004*9e564957SAndroid Build Coastguard Worker 			       struct iovec *iov, int iov_count,
1005*9e564957SAndroid Build Coastguard Worker 			       struct fuse_bufvec *buf, unsigned int flags)
1006*9e564957SAndroid Build Coastguard Worker {
1007*9e564957SAndroid Build Coastguard Worker 	size_t len = fuse_buf_size(buf);
1008*9e564957SAndroid Build Coastguard Worker 	(void) flags;
1009*9e564957SAndroid Build Coastguard Worker 
1010*9e564957SAndroid Build Coastguard Worker 	return fuse_send_data_iov_fallback(se, ch, iov, iov_count, buf, len);
1011*9e564957SAndroid Build Coastguard Worker }
1012*9e564957SAndroid Build Coastguard Worker #endif
1013*9e564957SAndroid Build Coastguard Worker 
1014*9e564957SAndroid Build Coastguard Worker int fuse_reply_data(fuse_req_t req, struct fuse_bufvec *bufv,
1015*9e564957SAndroid Build Coastguard Worker 		    enum fuse_buf_copy_flags flags)
1016*9e564957SAndroid Build Coastguard Worker {
1017*9e564957SAndroid Build Coastguard Worker 	struct iovec iov[2];
1018*9e564957SAndroid Build Coastguard Worker 	struct fuse_out_header out;
1019*9e564957SAndroid Build Coastguard Worker 	int res;
1020*9e564957SAndroid Build Coastguard Worker 
1021*9e564957SAndroid Build Coastguard Worker 	iov[0].iov_base = &out;
1022*9e564957SAndroid Build Coastguard Worker 	iov[0].iov_len = sizeof(struct fuse_out_header);
1023*9e564957SAndroid Build Coastguard Worker 
1024*9e564957SAndroid Build Coastguard Worker 	out.unique = req->unique;
1025*9e564957SAndroid Build Coastguard Worker 	out.error = 0;
1026*9e564957SAndroid Build Coastguard Worker 
1027*9e564957SAndroid Build Coastguard Worker 	res = fuse_send_data_iov(req->se, req->ch, iov, 1, bufv, flags);
1028*9e564957SAndroid Build Coastguard Worker 	if (res <= 0) {
1029*9e564957SAndroid Build Coastguard Worker 		fuse_free_req(req);
1030*9e564957SAndroid Build Coastguard Worker 		return res;
1031*9e564957SAndroid Build Coastguard Worker 	} else {
1032*9e564957SAndroid Build Coastguard Worker 		return fuse_reply_err(req, res);
1033*9e564957SAndroid Build Coastguard Worker 	}
1034*9e564957SAndroid Build Coastguard Worker }
1035*9e564957SAndroid Build Coastguard Worker 
1036*9e564957SAndroid Build Coastguard Worker int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf)
1037*9e564957SAndroid Build Coastguard Worker {
1038*9e564957SAndroid Build Coastguard Worker 	struct fuse_statfs_out arg;
1039*9e564957SAndroid Build Coastguard Worker 	size_t size = req->se->conn.proto_minor < 4 ?
1040*9e564957SAndroid Build Coastguard Worker 		FUSE_COMPAT_STATFS_SIZE : sizeof(arg);
1041*9e564957SAndroid Build Coastguard Worker 
1042*9e564957SAndroid Build Coastguard Worker 	memset(&arg, 0, sizeof(arg));
1043*9e564957SAndroid Build Coastguard Worker 	convert_statfs(stbuf, &arg.st);
1044*9e564957SAndroid Build Coastguard Worker 
1045*9e564957SAndroid Build Coastguard Worker 	return send_reply_ok(req, &arg, size);
1046*9e564957SAndroid Build Coastguard Worker }
1047*9e564957SAndroid Build Coastguard Worker 
1048*9e564957SAndroid Build Coastguard Worker int fuse_reply_xattr(fuse_req_t req, size_t count)
1049*9e564957SAndroid Build Coastguard Worker {
1050*9e564957SAndroid Build Coastguard Worker 	struct fuse_getxattr_out arg;
1051*9e564957SAndroid Build Coastguard Worker 
1052*9e564957SAndroid Build Coastguard Worker 	memset(&arg, 0, sizeof(arg));
1053*9e564957SAndroid Build Coastguard Worker 	arg.size = count;
1054*9e564957SAndroid Build Coastguard Worker 
1055*9e564957SAndroid Build Coastguard Worker 	return send_reply_ok(req, &arg, sizeof(arg));
1056*9e564957SAndroid Build Coastguard Worker }
1057*9e564957SAndroid Build Coastguard Worker 
1058*9e564957SAndroid Build Coastguard Worker int fuse_reply_lock(fuse_req_t req, const struct flock *lock)
1059*9e564957SAndroid Build Coastguard Worker {
1060*9e564957SAndroid Build Coastguard Worker 	struct fuse_lk_out arg;
1061*9e564957SAndroid Build Coastguard Worker 
1062*9e564957SAndroid Build Coastguard Worker 	memset(&arg, 0, sizeof(arg));
1063*9e564957SAndroid Build Coastguard Worker 	arg.lk.type = lock->l_type;
1064*9e564957SAndroid Build Coastguard Worker 	if (lock->l_type != F_UNLCK) {
1065*9e564957SAndroid Build Coastguard Worker 		arg.lk.start = lock->l_start;
1066*9e564957SAndroid Build Coastguard Worker 		if (lock->l_len == 0)
1067*9e564957SAndroid Build Coastguard Worker 			arg.lk.end = OFFSET_MAX;
1068*9e564957SAndroid Build Coastguard Worker 		else
1069*9e564957SAndroid Build Coastguard Worker 			arg.lk.end = lock->l_start + lock->l_len - 1;
1070*9e564957SAndroid Build Coastguard Worker 	}
1071*9e564957SAndroid Build Coastguard Worker 	arg.lk.pid = lock->l_pid;
1072*9e564957SAndroid Build Coastguard Worker 	return send_reply_ok(req, &arg, sizeof(arg));
1073*9e564957SAndroid Build Coastguard Worker }
1074*9e564957SAndroid Build Coastguard Worker 
1075*9e564957SAndroid Build Coastguard Worker int fuse_reply_bmap(fuse_req_t req, uint64_t idx)
1076*9e564957SAndroid Build Coastguard Worker {
1077*9e564957SAndroid Build Coastguard Worker 	struct fuse_bmap_out arg;
1078*9e564957SAndroid Build Coastguard Worker 
1079*9e564957SAndroid Build Coastguard Worker 	memset(&arg, 0, sizeof(arg));
1080*9e564957SAndroid Build Coastguard Worker 	arg.block = idx;
1081*9e564957SAndroid Build Coastguard Worker 
1082*9e564957SAndroid Build Coastguard Worker 	return send_reply_ok(req, &arg, sizeof(arg));
1083*9e564957SAndroid Build Coastguard Worker }
1084*9e564957SAndroid Build Coastguard Worker 
1085*9e564957SAndroid Build Coastguard Worker static struct fuse_ioctl_iovec *fuse_ioctl_iovec_copy(const struct iovec *iov,
1086*9e564957SAndroid Build Coastguard Worker 						      size_t count)
1087*9e564957SAndroid Build Coastguard Worker {
1088*9e564957SAndroid Build Coastguard Worker 	struct fuse_ioctl_iovec *fiov;
1089*9e564957SAndroid Build Coastguard Worker 	size_t i;
1090*9e564957SAndroid Build Coastguard Worker 
1091*9e564957SAndroid Build Coastguard Worker 	fiov = malloc(sizeof(fiov[0]) * count);
1092*9e564957SAndroid Build Coastguard Worker 	if (!fiov)
1093*9e564957SAndroid Build Coastguard Worker 		return NULL;
1094*9e564957SAndroid Build Coastguard Worker 
1095*9e564957SAndroid Build Coastguard Worker 	for (i = 0; i < count; i++) {
1096*9e564957SAndroid Build Coastguard Worker 		fiov[i].base = (uintptr_t) iov[i].iov_base;
1097*9e564957SAndroid Build Coastguard Worker 		fiov[i].len = iov[i].iov_len;
1098*9e564957SAndroid Build Coastguard Worker 	}
1099*9e564957SAndroid Build Coastguard Worker 
1100*9e564957SAndroid Build Coastguard Worker 	return fiov;
1101*9e564957SAndroid Build Coastguard Worker }
1102*9e564957SAndroid Build Coastguard Worker 
1103*9e564957SAndroid Build Coastguard Worker int fuse_reply_ioctl_retry(fuse_req_t req,
1104*9e564957SAndroid Build Coastguard Worker 			   const struct iovec *in_iov, size_t in_count,
1105*9e564957SAndroid Build Coastguard Worker 			   const struct iovec *out_iov, size_t out_count)
1106*9e564957SAndroid Build Coastguard Worker {
1107*9e564957SAndroid Build Coastguard Worker 	struct fuse_ioctl_out arg;
1108*9e564957SAndroid Build Coastguard Worker 	struct fuse_ioctl_iovec *in_fiov = NULL;
1109*9e564957SAndroid Build Coastguard Worker 	struct fuse_ioctl_iovec *out_fiov = NULL;
1110*9e564957SAndroid Build Coastguard Worker 	struct iovec iov[4];
1111*9e564957SAndroid Build Coastguard Worker 	size_t count = 1;
1112*9e564957SAndroid Build Coastguard Worker 	int res;
1113*9e564957SAndroid Build Coastguard Worker 
1114*9e564957SAndroid Build Coastguard Worker 	memset(&arg, 0, sizeof(arg));
1115*9e564957SAndroid Build Coastguard Worker 	arg.flags |= FUSE_IOCTL_RETRY;
1116*9e564957SAndroid Build Coastguard Worker 	arg.in_iovs = in_count;
1117*9e564957SAndroid Build Coastguard Worker 	arg.out_iovs = out_count;
1118*9e564957SAndroid Build Coastguard Worker 	iov[count].iov_base = &arg;
1119*9e564957SAndroid Build Coastguard Worker 	iov[count].iov_len = sizeof(arg);
1120*9e564957SAndroid Build Coastguard Worker 	count++;
1121*9e564957SAndroid Build Coastguard Worker 
1122*9e564957SAndroid Build Coastguard Worker 	if (req->se->conn.proto_minor < 16) {
1123*9e564957SAndroid Build Coastguard Worker 		if (in_count) {
1124*9e564957SAndroid Build Coastguard Worker 			iov[count].iov_base = (void *)in_iov;
1125*9e564957SAndroid Build Coastguard Worker 			iov[count].iov_len = sizeof(in_iov[0]) * in_count;
1126*9e564957SAndroid Build Coastguard Worker 			count++;
1127*9e564957SAndroid Build Coastguard Worker 		}
1128*9e564957SAndroid Build Coastguard Worker 
1129*9e564957SAndroid Build Coastguard Worker 		if (out_count) {
1130*9e564957SAndroid Build Coastguard Worker 			iov[count].iov_base = (void *)out_iov;
1131*9e564957SAndroid Build Coastguard Worker 			iov[count].iov_len = sizeof(out_iov[0]) * out_count;
1132*9e564957SAndroid Build Coastguard Worker 			count++;
1133*9e564957SAndroid Build Coastguard Worker 		}
1134*9e564957SAndroid Build Coastguard Worker 	} else {
1135*9e564957SAndroid Build Coastguard Worker 		/* Can't handle non-compat 64bit ioctls on 32bit */
1136*9e564957SAndroid Build Coastguard Worker 		if (sizeof(void *) == 4 && req->ioctl_64bit) {
1137*9e564957SAndroid Build Coastguard Worker 			res = fuse_reply_err(req, EINVAL);
1138*9e564957SAndroid Build Coastguard Worker 			goto out;
1139*9e564957SAndroid Build Coastguard Worker 		}
1140*9e564957SAndroid Build Coastguard Worker 
1141*9e564957SAndroid Build Coastguard Worker 		if (in_count) {
1142*9e564957SAndroid Build Coastguard Worker 			in_fiov = fuse_ioctl_iovec_copy(in_iov, in_count);
1143*9e564957SAndroid Build Coastguard Worker 			if (!in_fiov)
1144*9e564957SAndroid Build Coastguard Worker 				goto enomem;
1145*9e564957SAndroid Build Coastguard Worker 
1146*9e564957SAndroid Build Coastguard Worker 			iov[count].iov_base = (void *)in_fiov;
1147*9e564957SAndroid Build Coastguard Worker 			iov[count].iov_len = sizeof(in_fiov[0]) * in_count;
1148*9e564957SAndroid Build Coastguard Worker 			count++;
1149*9e564957SAndroid Build Coastguard Worker 		}
1150*9e564957SAndroid Build Coastguard Worker 		if (out_count) {
1151*9e564957SAndroid Build Coastguard Worker 			out_fiov = fuse_ioctl_iovec_copy(out_iov, out_count);
1152*9e564957SAndroid Build Coastguard Worker 			if (!out_fiov)
1153*9e564957SAndroid Build Coastguard Worker 				goto enomem;
1154*9e564957SAndroid Build Coastguard Worker 
1155*9e564957SAndroid Build Coastguard Worker 			iov[count].iov_base = (void *)out_fiov;
1156*9e564957SAndroid Build Coastguard Worker 			iov[count].iov_len = sizeof(out_fiov[0]) * out_count;
1157*9e564957SAndroid Build Coastguard Worker 			count++;
1158*9e564957SAndroid Build Coastguard Worker 		}
1159*9e564957SAndroid Build Coastguard Worker 	}
1160*9e564957SAndroid Build Coastguard Worker 
1161*9e564957SAndroid Build Coastguard Worker 	res = send_reply_iov(req, 0, iov, count);
1162*9e564957SAndroid Build Coastguard Worker out:
1163*9e564957SAndroid Build Coastguard Worker 	free(in_fiov);
1164*9e564957SAndroid Build Coastguard Worker 	free(out_fiov);
1165*9e564957SAndroid Build Coastguard Worker 
1166*9e564957SAndroid Build Coastguard Worker 	return res;
1167*9e564957SAndroid Build Coastguard Worker 
1168*9e564957SAndroid Build Coastguard Worker enomem:
1169*9e564957SAndroid Build Coastguard Worker 	res = fuse_reply_err(req, ENOMEM);
1170*9e564957SAndroid Build Coastguard Worker 	goto out;
1171*9e564957SAndroid Build Coastguard Worker }
1172*9e564957SAndroid Build Coastguard Worker 
1173*9e564957SAndroid Build Coastguard Worker int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size)
1174*9e564957SAndroid Build Coastguard Worker {
1175*9e564957SAndroid Build Coastguard Worker 	struct fuse_ioctl_out arg;
1176*9e564957SAndroid Build Coastguard Worker 	struct iovec iov[3];
1177*9e564957SAndroid Build Coastguard Worker 	size_t count = 1;
1178*9e564957SAndroid Build Coastguard Worker 
1179*9e564957SAndroid Build Coastguard Worker 	memset(&arg, 0, sizeof(arg));
1180*9e564957SAndroid Build Coastguard Worker 	arg.result = result;
1181*9e564957SAndroid Build Coastguard Worker 	iov[count].iov_base = &arg;
1182*9e564957SAndroid Build Coastguard Worker 	iov[count].iov_len = sizeof(arg);
1183*9e564957SAndroid Build Coastguard Worker 	count++;
1184*9e564957SAndroid Build Coastguard Worker 
1185*9e564957SAndroid Build Coastguard Worker 	if (size) {
1186*9e564957SAndroid Build Coastguard Worker 		iov[count].iov_base = (char *) buf;
1187*9e564957SAndroid Build Coastguard Worker 		iov[count].iov_len = size;
1188*9e564957SAndroid Build Coastguard Worker 		count++;
1189*9e564957SAndroid Build Coastguard Worker 	}
1190*9e564957SAndroid Build Coastguard Worker 
1191*9e564957SAndroid Build Coastguard Worker 	return send_reply_iov(req, 0, iov, count);
1192*9e564957SAndroid Build Coastguard Worker }
1193*9e564957SAndroid Build Coastguard Worker 
1194*9e564957SAndroid Build Coastguard Worker int fuse_reply_ioctl_iov(fuse_req_t req, int result, const struct iovec *iov,
1195*9e564957SAndroid Build Coastguard Worker 			 int count)
1196*9e564957SAndroid Build Coastguard Worker {
1197*9e564957SAndroid Build Coastguard Worker 	struct iovec *padded_iov;
1198*9e564957SAndroid Build Coastguard Worker 	struct fuse_ioctl_out arg;
1199*9e564957SAndroid Build Coastguard Worker 	int res;
1200*9e564957SAndroid Build Coastguard Worker 
1201*9e564957SAndroid Build Coastguard Worker 	padded_iov = malloc((count + 2) * sizeof(struct iovec));
1202*9e564957SAndroid Build Coastguard Worker 	if (padded_iov == NULL)
1203*9e564957SAndroid Build Coastguard Worker 		return fuse_reply_err(req, ENOMEM);
1204*9e564957SAndroid Build Coastguard Worker 
1205*9e564957SAndroid Build Coastguard Worker 	memset(&arg, 0, sizeof(arg));
1206*9e564957SAndroid Build Coastguard Worker 	arg.result = result;
1207*9e564957SAndroid Build Coastguard Worker 	padded_iov[1].iov_base = &arg;
1208*9e564957SAndroid Build Coastguard Worker 	padded_iov[1].iov_len = sizeof(arg);
1209*9e564957SAndroid Build Coastguard Worker 
1210*9e564957SAndroid Build Coastguard Worker 	memcpy(&padded_iov[2], iov, count * sizeof(struct iovec));
1211*9e564957SAndroid Build Coastguard Worker 
1212*9e564957SAndroid Build Coastguard Worker 	res = send_reply_iov(req, 0, padded_iov, count + 2);
1213*9e564957SAndroid Build Coastguard Worker 	free(padded_iov);
1214*9e564957SAndroid Build Coastguard Worker 
1215*9e564957SAndroid Build Coastguard Worker 	return res;
1216*9e564957SAndroid Build Coastguard Worker }
1217*9e564957SAndroid Build Coastguard Worker 
1218*9e564957SAndroid Build Coastguard Worker int fuse_reply_poll(fuse_req_t req, unsigned revents)
1219*9e564957SAndroid Build Coastguard Worker {
1220*9e564957SAndroid Build Coastguard Worker 	struct fuse_poll_out arg;
1221*9e564957SAndroid Build Coastguard Worker 
1222*9e564957SAndroid Build Coastguard Worker 	memset(&arg, 0, sizeof(arg));
1223*9e564957SAndroid Build Coastguard Worker 	arg.revents = revents;
1224*9e564957SAndroid Build Coastguard Worker 
1225*9e564957SAndroid Build Coastguard Worker 	return send_reply_ok(req, &arg, sizeof(arg));
1226*9e564957SAndroid Build Coastguard Worker }
1227*9e564957SAndroid Build Coastguard Worker 
1228*9e564957SAndroid Build Coastguard Worker int fuse_reply_lseek(fuse_req_t req, off_t off)
1229*9e564957SAndroid Build Coastguard Worker {
1230*9e564957SAndroid Build Coastguard Worker 	struct fuse_lseek_out arg;
1231*9e564957SAndroid Build Coastguard Worker 
1232*9e564957SAndroid Build Coastguard Worker 	memset(&arg, 0, sizeof(arg));
1233*9e564957SAndroid Build Coastguard Worker 	arg.offset = off;
1234*9e564957SAndroid Build Coastguard Worker 
1235*9e564957SAndroid Build Coastguard Worker 	return send_reply_ok(req, &arg, sizeof(arg));
1236*9e564957SAndroid Build Coastguard Worker }
1237*9e564957SAndroid Build Coastguard Worker 
1238*9e564957SAndroid Build Coastguard Worker static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1239*9e564957SAndroid Build Coastguard Worker {
1240*9e564957SAndroid Build Coastguard Worker 	char *name = (char *) inarg;
1241*9e564957SAndroid Build Coastguard Worker 
1242*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.lookup)
1243*9e564957SAndroid Build Coastguard Worker 		req->se->op.lookup(req, nodeid, name);
1244*9e564957SAndroid Build Coastguard Worker 	else
1245*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1246*9e564957SAndroid Build Coastguard Worker }
1247*9e564957SAndroid Build Coastguard Worker 
1248*9e564957SAndroid Build Coastguard Worker static void do_lookup_postfilter(fuse_req_t req, fuse_ino_t nodeid, uint32_t error_in,
1249*9e564957SAndroid Build Coastguard Worker 								 const void *inarg, size_t size)
1250*9e564957SAndroid Build Coastguard Worker {
1251*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.lookup_postfilter) {
1252*9e564957SAndroid Build Coastguard Worker 		char *name = (char *) inarg;
1253*9e564957SAndroid Build Coastguard Worker 		size_t namelen = strlen(name);
1254*9e564957SAndroid Build Coastguard Worker 
1255*9e564957SAndroid Build Coastguard Worker 		if (size != namelen + 1 + sizeof(struct fuse_entry_out)
1256*9e564957SAndroid Build Coastguard Worker 						+ sizeof(struct fuse_entry_bpf_out)) {
1257*9e564957SAndroid Build Coastguard Worker 			fuse_log(FUSE_LOG_ERR, "%s: Bad size", __func__);
1258*9e564957SAndroid Build Coastguard Worker 			fuse_reply_err(req, EIO);
1259*9e564957SAndroid Build Coastguard Worker 		} else {
1260*9e564957SAndroid Build Coastguard Worker 			struct fuse_entry_out *feo = (void *) (name + namelen + 1);
1261*9e564957SAndroid Build Coastguard Worker 			struct fuse_entry_bpf_out *febo = (char *) feo + sizeof(*feo);
1262*9e564957SAndroid Build Coastguard Worker 
1263*9e564957SAndroid Build Coastguard Worker 			req->se->op.lookup_postfilter(req, nodeid, error_in, name, feo,
1264*9e564957SAndroid Build Coastguard Worker 											febo);
1265*9e564957SAndroid Build Coastguard Worker 		}
1266*9e564957SAndroid Build Coastguard Worker 	} else
1267*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1268*9e564957SAndroid Build Coastguard Worker }
1269*9e564957SAndroid Build Coastguard Worker 
1270*9e564957SAndroid Build Coastguard Worker static void do_forget(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1271*9e564957SAndroid Build Coastguard Worker {
1272*9e564957SAndroid Build Coastguard Worker 	struct fuse_forget_in *arg = (struct fuse_forget_in *) inarg;
1273*9e564957SAndroid Build Coastguard Worker 
1274*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.forget)
1275*9e564957SAndroid Build Coastguard Worker 		req->se->op.forget(req, nodeid, arg->nlookup);
1276*9e564957SAndroid Build Coastguard Worker 	else
1277*9e564957SAndroid Build Coastguard Worker 		fuse_reply_none(req);
1278*9e564957SAndroid Build Coastguard Worker }
1279*9e564957SAndroid Build Coastguard Worker 
1280*9e564957SAndroid Build Coastguard Worker static void do_batch_forget(fuse_req_t req, fuse_ino_t nodeid,
1281*9e564957SAndroid Build Coastguard Worker 			    const void *inarg)
1282*9e564957SAndroid Build Coastguard Worker {
1283*9e564957SAndroid Build Coastguard Worker 	struct fuse_batch_forget_in *arg = (void *) inarg;
1284*9e564957SAndroid Build Coastguard Worker 	struct fuse_forget_one *param = (void *) PARAM(arg);
1285*9e564957SAndroid Build Coastguard Worker 	unsigned int i;
1286*9e564957SAndroid Build Coastguard Worker 
1287*9e564957SAndroid Build Coastguard Worker 	(void) nodeid;
1288*9e564957SAndroid Build Coastguard Worker 
1289*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.forget_multi) {
1290*9e564957SAndroid Build Coastguard Worker 		req->se->op.forget_multi(req, arg->count,
1291*9e564957SAndroid Build Coastguard Worker 				     (struct fuse_forget_data *) param);
1292*9e564957SAndroid Build Coastguard Worker 	} else if (req->se->op.forget) {
1293*9e564957SAndroid Build Coastguard Worker 		for (i = 0; i < arg->count; i++) {
1294*9e564957SAndroid Build Coastguard Worker 			struct fuse_forget_one *forget = &param[i];
1295*9e564957SAndroid Build Coastguard Worker 			struct fuse_req *dummy_req;
1296*9e564957SAndroid Build Coastguard Worker 
1297*9e564957SAndroid Build Coastguard Worker 			dummy_req = fuse_ll_alloc_req(req->se);
1298*9e564957SAndroid Build Coastguard Worker 			if (dummy_req == NULL)
1299*9e564957SAndroid Build Coastguard Worker 				break;
1300*9e564957SAndroid Build Coastguard Worker 
1301*9e564957SAndroid Build Coastguard Worker 			dummy_req->unique = req->unique;
1302*9e564957SAndroid Build Coastguard Worker 			dummy_req->ctx = req->ctx;
1303*9e564957SAndroid Build Coastguard Worker 			dummy_req->ch = NULL;
1304*9e564957SAndroid Build Coastguard Worker 
1305*9e564957SAndroid Build Coastguard Worker 			req->se->op.forget(dummy_req, forget->nodeid,
1306*9e564957SAndroid Build Coastguard Worker 					  forget->nlookup);
1307*9e564957SAndroid Build Coastguard Worker 		}
1308*9e564957SAndroid Build Coastguard Worker 		fuse_reply_none(req);
1309*9e564957SAndroid Build Coastguard Worker 	} else {
1310*9e564957SAndroid Build Coastguard Worker 		fuse_reply_none(req);
1311*9e564957SAndroid Build Coastguard Worker 	}
1312*9e564957SAndroid Build Coastguard Worker }
1313*9e564957SAndroid Build Coastguard Worker 
1314*9e564957SAndroid Build Coastguard Worker static void do_getattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1315*9e564957SAndroid Build Coastguard Worker {
1316*9e564957SAndroid Build Coastguard Worker 	struct fuse_file_info *fip = NULL;
1317*9e564957SAndroid Build Coastguard Worker 	struct fuse_file_info fi;
1318*9e564957SAndroid Build Coastguard Worker 
1319*9e564957SAndroid Build Coastguard Worker 	if (req->se->conn.proto_minor >= 9) {
1320*9e564957SAndroid Build Coastguard Worker 		struct fuse_getattr_in *arg = (struct fuse_getattr_in *) inarg;
1321*9e564957SAndroid Build Coastguard Worker 
1322*9e564957SAndroid Build Coastguard Worker 		if (arg->getattr_flags & FUSE_GETATTR_FH) {
1323*9e564957SAndroid Build Coastguard Worker 			memset(&fi, 0, sizeof(fi));
1324*9e564957SAndroid Build Coastguard Worker 			fi.fh = arg->fh;
1325*9e564957SAndroid Build Coastguard Worker 			fip = &fi;
1326*9e564957SAndroid Build Coastguard Worker 		}
1327*9e564957SAndroid Build Coastguard Worker 	}
1328*9e564957SAndroid Build Coastguard Worker 
1329*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.getattr)
1330*9e564957SAndroid Build Coastguard Worker 		req->se->op.getattr(req, nodeid, fip);
1331*9e564957SAndroid Build Coastguard Worker 	else
1332*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1333*9e564957SAndroid Build Coastguard Worker }
1334*9e564957SAndroid Build Coastguard Worker 
1335*9e564957SAndroid Build Coastguard Worker static void do_setattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1336*9e564957SAndroid Build Coastguard Worker {
1337*9e564957SAndroid Build Coastguard Worker 	struct fuse_setattr_in *arg = (struct fuse_setattr_in *) inarg;
1338*9e564957SAndroid Build Coastguard Worker 
1339*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.setattr) {
1340*9e564957SAndroid Build Coastguard Worker 		struct fuse_file_info *fi = NULL;
1341*9e564957SAndroid Build Coastguard Worker 		struct fuse_file_info fi_store;
1342*9e564957SAndroid Build Coastguard Worker 		struct stat stbuf;
1343*9e564957SAndroid Build Coastguard Worker 		memset(&stbuf, 0, sizeof(stbuf));
1344*9e564957SAndroid Build Coastguard Worker 		convert_attr(arg, &stbuf);
1345*9e564957SAndroid Build Coastguard Worker 		if (arg->valid & FATTR_FH) {
1346*9e564957SAndroid Build Coastguard Worker 			arg->valid &= ~FATTR_FH;
1347*9e564957SAndroid Build Coastguard Worker 			memset(&fi_store, 0, sizeof(fi_store));
1348*9e564957SAndroid Build Coastguard Worker 			fi = &fi_store;
1349*9e564957SAndroid Build Coastguard Worker 			fi->fh = arg->fh;
1350*9e564957SAndroid Build Coastguard Worker 		}
1351*9e564957SAndroid Build Coastguard Worker 		arg->valid &=
1352*9e564957SAndroid Build Coastguard Worker 			FUSE_SET_ATTR_MODE	|
1353*9e564957SAndroid Build Coastguard Worker 			FUSE_SET_ATTR_UID	|
1354*9e564957SAndroid Build Coastguard Worker 			FUSE_SET_ATTR_GID	|
1355*9e564957SAndroid Build Coastguard Worker 			FUSE_SET_ATTR_SIZE	|
1356*9e564957SAndroid Build Coastguard Worker 			FUSE_SET_ATTR_ATIME	|
1357*9e564957SAndroid Build Coastguard Worker 			FUSE_SET_ATTR_MTIME	|
1358*9e564957SAndroid Build Coastguard Worker 			FUSE_SET_ATTR_KILL_SUID |
1359*9e564957SAndroid Build Coastguard Worker 			FUSE_SET_ATTR_KILL_SGID |
1360*9e564957SAndroid Build Coastguard Worker 			FUSE_SET_ATTR_ATIME_NOW	|
1361*9e564957SAndroid Build Coastguard Worker 			FUSE_SET_ATTR_MTIME_NOW |
1362*9e564957SAndroid Build Coastguard Worker 			FUSE_SET_ATTR_CTIME;
1363*9e564957SAndroid Build Coastguard Worker 
1364*9e564957SAndroid Build Coastguard Worker 		req->se->op.setattr(req, nodeid, &stbuf, arg->valid, fi);
1365*9e564957SAndroid Build Coastguard Worker 	} else
1366*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1367*9e564957SAndroid Build Coastguard Worker }
1368*9e564957SAndroid Build Coastguard Worker 
1369*9e564957SAndroid Build Coastguard Worker static void do_access(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1370*9e564957SAndroid Build Coastguard Worker {
1371*9e564957SAndroid Build Coastguard Worker 	struct fuse_access_in *arg = (struct fuse_access_in *) inarg;
1372*9e564957SAndroid Build Coastguard Worker 
1373*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.access)
1374*9e564957SAndroid Build Coastguard Worker 		req->se->op.access(req, nodeid, arg->mask);
1375*9e564957SAndroid Build Coastguard Worker 	else
1376*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1377*9e564957SAndroid Build Coastguard Worker }
1378*9e564957SAndroid Build Coastguard Worker 
1379*9e564957SAndroid Build Coastguard Worker static void do_readlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1380*9e564957SAndroid Build Coastguard Worker {
1381*9e564957SAndroid Build Coastguard Worker 	(void) inarg;
1382*9e564957SAndroid Build Coastguard Worker 
1383*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.readlink)
1384*9e564957SAndroid Build Coastguard Worker 		req->se->op.readlink(req, nodeid);
1385*9e564957SAndroid Build Coastguard Worker 	else
1386*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1387*9e564957SAndroid Build Coastguard Worker }
1388*9e564957SAndroid Build Coastguard Worker 
1389*9e564957SAndroid Build Coastguard Worker static void do_canonical_path(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1390*9e564957SAndroid Build Coastguard Worker {
1391*9e564957SAndroid Build Coastguard Worker 	(void) inarg;
1392*9e564957SAndroid Build Coastguard Worker 
1393*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.canonical_path)
1394*9e564957SAndroid Build Coastguard Worker 		req->se->op.canonical_path(req, nodeid);
1395*9e564957SAndroid Build Coastguard Worker 	else
1396*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1397*9e564957SAndroid Build Coastguard Worker }
1398*9e564957SAndroid Build Coastguard Worker 
1399*9e564957SAndroid Build Coastguard Worker static void do_mknod(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1400*9e564957SAndroid Build Coastguard Worker {
1401*9e564957SAndroid Build Coastguard Worker 	struct fuse_mknod_in *arg = (struct fuse_mknod_in *) inarg;
1402*9e564957SAndroid Build Coastguard Worker 	char *name = PARAM(arg);
1403*9e564957SAndroid Build Coastguard Worker 
1404*9e564957SAndroid Build Coastguard Worker 	if (req->se->conn.proto_minor >= 12)
1405*9e564957SAndroid Build Coastguard Worker 		req->ctx.umask = arg->umask;
1406*9e564957SAndroid Build Coastguard Worker 	else
1407*9e564957SAndroid Build Coastguard Worker 		name = (char *) inarg + FUSE_COMPAT_MKNOD_IN_SIZE;
1408*9e564957SAndroid Build Coastguard Worker 
1409*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.mknod)
1410*9e564957SAndroid Build Coastguard Worker 		req->se->op.mknod(req, nodeid, name, arg->mode, arg->rdev);
1411*9e564957SAndroid Build Coastguard Worker 	else
1412*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1413*9e564957SAndroid Build Coastguard Worker }
1414*9e564957SAndroid Build Coastguard Worker 
1415*9e564957SAndroid Build Coastguard Worker static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1416*9e564957SAndroid Build Coastguard Worker {
1417*9e564957SAndroid Build Coastguard Worker 	struct fuse_mkdir_in *arg = (struct fuse_mkdir_in *) inarg;
1418*9e564957SAndroid Build Coastguard Worker 
1419*9e564957SAndroid Build Coastguard Worker 	if (req->se->conn.proto_minor >= 12)
1420*9e564957SAndroid Build Coastguard Worker 		req->ctx.umask = arg->umask;
1421*9e564957SAndroid Build Coastguard Worker 
1422*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.mkdir)
1423*9e564957SAndroid Build Coastguard Worker 		req->se->op.mkdir(req, nodeid, PARAM(arg), arg->mode);
1424*9e564957SAndroid Build Coastguard Worker 	else
1425*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1426*9e564957SAndroid Build Coastguard Worker }
1427*9e564957SAndroid Build Coastguard Worker 
1428*9e564957SAndroid Build Coastguard Worker static void do_unlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1429*9e564957SAndroid Build Coastguard Worker {
1430*9e564957SAndroid Build Coastguard Worker 	char *name = (char *) inarg;
1431*9e564957SAndroid Build Coastguard Worker 
1432*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.unlink)
1433*9e564957SAndroid Build Coastguard Worker 		req->se->op.unlink(req, nodeid, name);
1434*9e564957SAndroid Build Coastguard Worker 	else
1435*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1436*9e564957SAndroid Build Coastguard Worker }
1437*9e564957SAndroid Build Coastguard Worker 
1438*9e564957SAndroid Build Coastguard Worker static void do_rmdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1439*9e564957SAndroid Build Coastguard Worker {
1440*9e564957SAndroid Build Coastguard Worker 	char *name = (char *) inarg;
1441*9e564957SAndroid Build Coastguard Worker 
1442*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.rmdir)
1443*9e564957SAndroid Build Coastguard Worker 		req->se->op.rmdir(req, nodeid, name);
1444*9e564957SAndroid Build Coastguard Worker 	else
1445*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1446*9e564957SAndroid Build Coastguard Worker }
1447*9e564957SAndroid Build Coastguard Worker 
1448*9e564957SAndroid Build Coastguard Worker static void do_symlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1449*9e564957SAndroid Build Coastguard Worker {
1450*9e564957SAndroid Build Coastguard Worker 	char *name = (char *) inarg;
1451*9e564957SAndroid Build Coastguard Worker 	char *linkname = ((char *) inarg) + strlen((char *) inarg) + 1;
1452*9e564957SAndroid Build Coastguard Worker 
1453*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.symlink)
1454*9e564957SAndroid Build Coastguard Worker 		req->se->op.symlink(req, linkname, nodeid, name);
1455*9e564957SAndroid Build Coastguard Worker 	else
1456*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1457*9e564957SAndroid Build Coastguard Worker }
1458*9e564957SAndroid Build Coastguard Worker 
1459*9e564957SAndroid Build Coastguard Worker static void do_rename(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1460*9e564957SAndroid Build Coastguard Worker {
1461*9e564957SAndroid Build Coastguard Worker 	struct fuse_rename_in *arg = (struct fuse_rename_in *) inarg;
1462*9e564957SAndroid Build Coastguard Worker 	char *oldname = PARAM(arg);
1463*9e564957SAndroid Build Coastguard Worker 	char *newname = oldname + strlen(oldname) + 1;
1464*9e564957SAndroid Build Coastguard Worker 
1465*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.rename)
1466*9e564957SAndroid Build Coastguard Worker 		req->se->op.rename(req, nodeid, oldname, arg->newdir, newname,
1467*9e564957SAndroid Build Coastguard Worker 				  0);
1468*9e564957SAndroid Build Coastguard Worker 	else
1469*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1470*9e564957SAndroid Build Coastguard Worker }
1471*9e564957SAndroid Build Coastguard Worker 
1472*9e564957SAndroid Build Coastguard Worker static void do_rename2(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1473*9e564957SAndroid Build Coastguard Worker {
1474*9e564957SAndroid Build Coastguard Worker 	struct fuse_rename2_in *arg = (struct fuse_rename2_in *) inarg;
1475*9e564957SAndroid Build Coastguard Worker 	char *oldname = PARAM(arg);
1476*9e564957SAndroid Build Coastguard Worker 	char *newname = oldname + strlen(oldname) + 1;
1477*9e564957SAndroid Build Coastguard Worker 
1478*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.rename)
1479*9e564957SAndroid Build Coastguard Worker 		req->se->op.rename(req, nodeid, oldname, arg->newdir, newname,
1480*9e564957SAndroid Build Coastguard Worker 				  arg->flags);
1481*9e564957SAndroid Build Coastguard Worker 	else
1482*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1483*9e564957SAndroid Build Coastguard Worker }
1484*9e564957SAndroid Build Coastguard Worker 
1485*9e564957SAndroid Build Coastguard Worker static void do_link(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1486*9e564957SAndroid Build Coastguard Worker {
1487*9e564957SAndroid Build Coastguard Worker 	struct fuse_link_in *arg = (struct fuse_link_in *) inarg;
1488*9e564957SAndroid Build Coastguard Worker 
1489*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.link)
1490*9e564957SAndroid Build Coastguard Worker 		req->se->op.link(req, arg->oldnodeid, nodeid, PARAM(arg));
1491*9e564957SAndroid Build Coastguard Worker 	else
1492*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1493*9e564957SAndroid Build Coastguard Worker }
1494*9e564957SAndroid Build Coastguard Worker 
1495*9e564957SAndroid Build Coastguard Worker static void do_create(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1496*9e564957SAndroid Build Coastguard Worker {
1497*9e564957SAndroid Build Coastguard Worker 	struct fuse_create_in *arg = (struct fuse_create_in *) inarg;
1498*9e564957SAndroid Build Coastguard Worker 
1499*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.create) {
1500*9e564957SAndroid Build Coastguard Worker 		struct fuse_file_info fi;
1501*9e564957SAndroid Build Coastguard Worker 		char *name = PARAM(arg);
1502*9e564957SAndroid Build Coastguard Worker 
1503*9e564957SAndroid Build Coastguard Worker 		memset(&fi, 0, sizeof(fi));
1504*9e564957SAndroid Build Coastguard Worker 		fi.flags = arg->flags;
1505*9e564957SAndroid Build Coastguard Worker 
1506*9e564957SAndroid Build Coastguard Worker 		if (req->se->conn.proto_minor >= 12)
1507*9e564957SAndroid Build Coastguard Worker 			req->ctx.umask = arg->umask;
1508*9e564957SAndroid Build Coastguard Worker 		else
1509*9e564957SAndroid Build Coastguard Worker 			name = (char *) inarg + sizeof(struct fuse_open_in);
1510*9e564957SAndroid Build Coastguard Worker 
1511*9e564957SAndroid Build Coastguard Worker 		req->se->op.create(req, nodeid, name, arg->mode, &fi);
1512*9e564957SAndroid Build Coastguard Worker 	} else
1513*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1514*9e564957SAndroid Build Coastguard Worker }
1515*9e564957SAndroid Build Coastguard Worker 
1516*9e564957SAndroid Build Coastguard Worker static void do_open(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1517*9e564957SAndroid Build Coastguard Worker {
1518*9e564957SAndroid Build Coastguard Worker 	struct fuse_open_in *arg = (struct fuse_open_in *) inarg;
1519*9e564957SAndroid Build Coastguard Worker 	struct fuse_file_info fi;
1520*9e564957SAndroid Build Coastguard Worker 
1521*9e564957SAndroid Build Coastguard Worker 	memset(&fi, 0, sizeof(fi));
1522*9e564957SAndroid Build Coastguard Worker 	fi.flags = arg->flags;
1523*9e564957SAndroid Build Coastguard Worker 
1524*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.open)
1525*9e564957SAndroid Build Coastguard Worker 		req->se->op.open(req, nodeid, &fi);
1526*9e564957SAndroid Build Coastguard Worker 	else if (req->se->conn.want & FUSE_CAP_NO_OPEN_SUPPORT)
1527*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1528*9e564957SAndroid Build Coastguard Worker 	else
1529*9e564957SAndroid Build Coastguard Worker 		fuse_reply_open(req, &fi);
1530*9e564957SAndroid Build Coastguard Worker }
1531*9e564957SAndroid Build Coastguard Worker 
1532*9e564957SAndroid Build Coastguard Worker static void do_read(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1533*9e564957SAndroid Build Coastguard Worker {
1534*9e564957SAndroid Build Coastguard Worker 	struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
1535*9e564957SAndroid Build Coastguard Worker 
1536*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.read) {
1537*9e564957SAndroid Build Coastguard Worker 		struct fuse_file_info fi;
1538*9e564957SAndroid Build Coastguard Worker 
1539*9e564957SAndroid Build Coastguard Worker 		memset(&fi, 0, sizeof(fi));
1540*9e564957SAndroid Build Coastguard Worker 		fi.fh = arg->fh;
1541*9e564957SAndroid Build Coastguard Worker 		if (req->se->conn.proto_minor >= 9) {
1542*9e564957SAndroid Build Coastguard Worker 			fi.lock_owner = arg->lock_owner;
1543*9e564957SAndroid Build Coastguard Worker 			fi.flags = arg->flags;
1544*9e564957SAndroid Build Coastguard Worker 		}
1545*9e564957SAndroid Build Coastguard Worker 		req->se->op.read(req, nodeid, arg->size, arg->offset, &fi);
1546*9e564957SAndroid Build Coastguard Worker 	} else
1547*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1548*9e564957SAndroid Build Coastguard Worker }
1549*9e564957SAndroid Build Coastguard Worker 
1550*9e564957SAndroid Build Coastguard Worker static void do_write(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1551*9e564957SAndroid Build Coastguard Worker {
1552*9e564957SAndroid Build Coastguard Worker 	struct fuse_write_in *arg = (struct fuse_write_in *) inarg;
1553*9e564957SAndroid Build Coastguard Worker 	struct fuse_file_info fi;
1554*9e564957SAndroid Build Coastguard Worker 	char *param;
1555*9e564957SAndroid Build Coastguard Worker 
1556*9e564957SAndroid Build Coastguard Worker 	memset(&fi, 0, sizeof(fi));
1557*9e564957SAndroid Build Coastguard Worker 	fi.fh = arg->fh;
1558*9e564957SAndroid Build Coastguard Worker 	fi.writepage = (arg->write_flags & FUSE_WRITE_CACHE) != 0;
1559*9e564957SAndroid Build Coastguard Worker 
1560*9e564957SAndroid Build Coastguard Worker 	if (req->se->conn.proto_minor < 9) {
1561*9e564957SAndroid Build Coastguard Worker 		param = ((char *) arg) + FUSE_COMPAT_WRITE_IN_SIZE;
1562*9e564957SAndroid Build Coastguard Worker 	} else {
1563*9e564957SAndroid Build Coastguard Worker 		fi.lock_owner = arg->lock_owner;
1564*9e564957SAndroid Build Coastguard Worker 		fi.flags = arg->flags;
1565*9e564957SAndroid Build Coastguard Worker 		param = PARAM(arg);
1566*9e564957SAndroid Build Coastguard Worker 	}
1567*9e564957SAndroid Build Coastguard Worker 
1568*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.write)
1569*9e564957SAndroid Build Coastguard Worker 		req->se->op.write(req, nodeid, param, arg->size,
1570*9e564957SAndroid Build Coastguard Worker 				 arg->offset, &fi);
1571*9e564957SAndroid Build Coastguard Worker 	else
1572*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1573*9e564957SAndroid Build Coastguard Worker }
1574*9e564957SAndroid Build Coastguard Worker 
1575*9e564957SAndroid Build Coastguard Worker static void do_write_buf(fuse_req_t req, fuse_ino_t nodeid, const void *inarg,
1576*9e564957SAndroid Build Coastguard Worker 			 const struct fuse_buf *ibuf)
1577*9e564957SAndroid Build Coastguard Worker {
1578*9e564957SAndroid Build Coastguard Worker 	struct fuse_session *se = req->se;
1579*9e564957SAndroid Build Coastguard Worker 	struct fuse_bufvec bufv = {
1580*9e564957SAndroid Build Coastguard Worker 		.buf[0] = *ibuf,
1581*9e564957SAndroid Build Coastguard Worker 		.count = 1,
1582*9e564957SAndroid Build Coastguard Worker 	};
1583*9e564957SAndroid Build Coastguard Worker 	struct fuse_write_in *arg = (struct fuse_write_in *) inarg;
1584*9e564957SAndroid Build Coastguard Worker 	struct fuse_file_info fi;
1585*9e564957SAndroid Build Coastguard Worker 
1586*9e564957SAndroid Build Coastguard Worker 	memset(&fi, 0, sizeof(fi));
1587*9e564957SAndroid Build Coastguard Worker 	fi.fh = arg->fh;
1588*9e564957SAndroid Build Coastguard Worker 	fi.writepage = arg->write_flags & FUSE_WRITE_CACHE;
1589*9e564957SAndroid Build Coastguard Worker 
1590*9e564957SAndroid Build Coastguard Worker 	if (se->conn.proto_minor < 9) {
1591*9e564957SAndroid Build Coastguard Worker 		bufv.buf[0].mem = ((char *) arg) + FUSE_COMPAT_WRITE_IN_SIZE;
1592*9e564957SAndroid Build Coastguard Worker 		bufv.buf[0].size -= sizeof(struct fuse_in_header) +
1593*9e564957SAndroid Build Coastguard Worker 			FUSE_COMPAT_WRITE_IN_SIZE;
1594*9e564957SAndroid Build Coastguard Worker 		assert(!(bufv.buf[0].flags & FUSE_BUF_IS_FD));
1595*9e564957SAndroid Build Coastguard Worker 	} else {
1596*9e564957SAndroid Build Coastguard Worker 		fi.lock_owner = arg->lock_owner;
1597*9e564957SAndroid Build Coastguard Worker 		fi.flags = arg->flags;
1598*9e564957SAndroid Build Coastguard Worker 		if (!(bufv.buf[0].flags & FUSE_BUF_IS_FD))
1599*9e564957SAndroid Build Coastguard Worker 			bufv.buf[0].mem = PARAM(arg);
1600*9e564957SAndroid Build Coastguard Worker 
1601*9e564957SAndroid Build Coastguard Worker 		bufv.buf[0].size -= sizeof(struct fuse_in_header) +
1602*9e564957SAndroid Build Coastguard Worker 			sizeof(struct fuse_write_in);
1603*9e564957SAndroid Build Coastguard Worker 	}
1604*9e564957SAndroid Build Coastguard Worker 	if (bufv.buf[0].size < arg->size) {
1605*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: do_write_buf: buffer size too small\n");
1606*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, EIO);
1607*9e564957SAndroid Build Coastguard Worker 		goto out;
1608*9e564957SAndroid Build Coastguard Worker 	}
1609*9e564957SAndroid Build Coastguard Worker 	bufv.buf[0].size = arg->size;
1610*9e564957SAndroid Build Coastguard Worker 
1611*9e564957SAndroid Build Coastguard Worker 	se->op.write_buf(req, nodeid, &bufv, arg->offset, &fi);
1612*9e564957SAndroid Build Coastguard Worker 
1613*9e564957SAndroid Build Coastguard Worker out:
1614*9e564957SAndroid Build Coastguard Worker 	/* Need to reset the pipe if ->write_buf() didn't consume all data */
1615*9e564957SAndroid Build Coastguard Worker 	if ((ibuf->flags & FUSE_BUF_IS_FD) && bufv.idx < bufv.count)
1616*9e564957SAndroid Build Coastguard Worker 		fuse_ll_clear_pipe(se);
1617*9e564957SAndroid Build Coastguard Worker }
1618*9e564957SAndroid Build Coastguard Worker 
1619*9e564957SAndroid Build Coastguard Worker static void do_flush(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1620*9e564957SAndroid Build Coastguard Worker {
1621*9e564957SAndroid Build Coastguard Worker 	struct fuse_flush_in *arg = (struct fuse_flush_in *) inarg;
1622*9e564957SAndroid Build Coastguard Worker 	struct fuse_file_info fi;
1623*9e564957SAndroid Build Coastguard Worker 
1624*9e564957SAndroid Build Coastguard Worker 	memset(&fi, 0, sizeof(fi));
1625*9e564957SAndroid Build Coastguard Worker 	fi.fh = arg->fh;
1626*9e564957SAndroid Build Coastguard Worker 	fi.flush = 1;
1627*9e564957SAndroid Build Coastguard Worker 	if (req->se->conn.proto_minor >= 7)
1628*9e564957SAndroid Build Coastguard Worker 		fi.lock_owner = arg->lock_owner;
1629*9e564957SAndroid Build Coastguard Worker 
1630*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.flush)
1631*9e564957SAndroid Build Coastguard Worker 		req->se->op.flush(req, nodeid, &fi);
1632*9e564957SAndroid Build Coastguard Worker 	else
1633*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1634*9e564957SAndroid Build Coastguard Worker }
1635*9e564957SAndroid Build Coastguard Worker 
1636*9e564957SAndroid Build Coastguard Worker static void do_release(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1637*9e564957SAndroid Build Coastguard Worker {
1638*9e564957SAndroid Build Coastguard Worker 	struct fuse_release_in *arg = (struct fuse_release_in *) inarg;
1639*9e564957SAndroid Build Coastguard Worker 	struct fuse_file_info fi;
1640*9e564957SAndroid Build Coastguard Worker 
1641*9e564957SAndroid Build Coastguard Worker 	memset(&fi, 0, sizeof(fi));
1642*9e564957SAndroid Build Coastguard Worker 	fi.flags = arg->flags;
1643*9e564957SAndroid Build Coastguard Worker 	fi.fh = arg->fh;
1644*9e564957SAndroid Build Coastguard Worker 	if (req->se->conn.proto_minor >= 8) {
1645*9e564957SAndroid Build Coastguard Worker 		fi.flush = (arg->release_flags & FUSE_RELEASE_FLUSH) ? 1 : 0;
1646*9e564957SAndroid Build Coastguard Worker 		fi.lock_owner = arg->lock_owner;
1647*9e564957SAndroid Build Coastguard Worker 	}
1648*9e564957SAndroid Build Coastguard Worker 	if (arg->release_flags & FUSE_RELEASE_FLOCK_UNLOCK) {
1649*9e564957SAndroid Build Coastguard Worker 		fi.flock_release = 1;
1650*9e564957SAndroid Build Coastguard Worker 		fi.lock_owner = arg->lock_owner;
1651*9e564957SAndroid Build Coastguard Worker 	}
1652*9e564957SAndroid Build Coastguard Worker 
1653*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.release)
1654*9e564957SAndroid Build Coastguard Worker 		req->se->op.release(req, nodeid, &fi);
1655*9e564957SAndroid Build Coastguard Worker 	else
1656*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, 0);
1657*9e564957SAndroid Build Coastguard Worker }
1658*9e564957SAndroid Build Coastguard Worker 
1659*9e564957SAndroid Build Coastguard Worker static void do_fsync(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1660*9e564957SAndroid Build Coastguard Worker {
1661*9e564957SAndroid Build Coastguard Worker 	struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg;
1662*9e564957SAndroid Build Coastguard Worker 	struct fuse_file_info fi;
1663*9e564957SAndroid Build Coastguard Worker 	int datasync = arg->fsync_flags & 1;
1664*9e564957SAndroid Build Coastguard Worker 
1665*9e564957SAndroid Build Coastguard Worker 	memset(&fi, 0, sizeof(fi));
1666*9e564957SAndroid Build Coastguard Worker 	fi.fh = arg->fh;
1667*9e564957SAndroid Build Coastguard Worker 
1668*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.fsync)
1669*9e564957SAndroid Build Coastguard Worker 		req->se->op.fsync(req, nodeid, datasync, &fi);
1670*9e564957SAndroid Build Coastguard Worker 	else
1671*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1672*9e564957SAndroid Build Coastguard Worker }
1673*9e564957SAndroid Build Coastguard Worker 
1674*9e564957SAndroid Build Coastguard Worker static void do_opendir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1675*9e564957SAndroid Build Coastguard Worker {
1676*9e564957SAndroid Build Coastguard Worker 	struct fuse_open_in *arg = (struct fuse_open_in *) inarg;
1677*9e564957SAndroid Build Coastguard Worker 	struct fuse_file_info fi;
1678*9e564957SAndroid Build Coastguard Worker 
1679*9e564957SAndroid Build Coastguard Worker 	memset(&fi, 0, sizeof(fi));
1680*9e564957SAndroid Build Coastguard Worker 	fi.flags = arg->flags;
1681*9e564957SAndroid Build Coastguard Worker 
1682*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.opendir)
1683*9e564957SAndroid Build Coastguard Worker 		req->se->op.opendir(req, nodeid, &fi);
1684*9e564957SAndroid Build Coastguard Worker 	else if (req->se->conn.want & FUSE_CAP_NO_OPENDIR_SUPPORT)
1685*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1686*9e564957SAndroid Build Coastguard Worker 	else
1687*9e564957SAndroid Build Coastguard Worker 		fuse_reply_open(req, &fi);
1688*9e564957SAndroid Build Coastguard Worker }
1689*9e564957SAndroid Build Coastguard Worker 
1690*9e564957SAndroid Build Coastguard Worker static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1691*9e564957SAndroid Build Coastguard Worker {
1692*9e564957SAndroid Build Coastguard Worker 	struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
1693*9e564957SAndroid Build Coastguard Worker 	struct fuse_file_info fi;
1694*9e564957SAndroid Build Coastguard Worker 
1695*9e564957SAndroid Build Coastguard Worker 	memset(&fi, 0, sizeof(fi));
1696*9e564957SAndroid Build Coastguard Worker 	fi.fh = arg->fh;
1697*9e564957SAndroid Build Coastguard Worker 
1698*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.readdir)
1699*9e564957SAndroid Build Coastguard Worker 		req->se->op.readdir(req, nodeid, arg->size, arg->offset, &fi);
1700*9e564957SAndroid Build Coastguard Worker 	else
1701*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1702*9e564957SAndroid Build Coastguard Worker }
1703*9e564957SAndroid Build Coastguard Worker 
1704*9e564957SAndroid Build Coastguard Worker static void do_readdirplus(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1705*9e564957SAndroid Build Coastguard Worker {
1706*9e564957SAndroid Build Coastguard Worker 	struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
1707*9e564957SAndroid Build Coastguard Worker 	struct fuse_file_info fi;
1708*9e564957SAndroid Build Coastguard Worker 
1709*9e564957SAndroid Build Coastguard Worker 	memset(&fi, 0, sizeof(fi));
1710*9e564957SAndroid Build Coastguard Worker 	fi.fh = arg->fh;
1711*9e564957SAndroid Build Coastguard Worker 
1712*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.readdirplus)
1713*9e564957SAndroid Build Coastguard Worker 		req->se->op.readdirplus(req, nodeid, arg->size, arg->offset, &fi);
1714*9e564957SAndroid Build Coastguard Worker 	else
1715*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1716*9e564957SAndroid Build Coastguard Worker }
1717*9e564957SAndroid Build Coastguard Worker 
1718*9e564957SAndroid Build Coastguard Worker static void do_readdir_postfilter(fuse_req_t req, fuse_ino_t nodeid,
1719*9e564957SAndroid Build Coastguard Worker 									uint32_t error_in, const void *inarg,
1720*9e564957SAndroid Build Coastguard Worker 									size_t size) {
1721*9e564957SAndroid Build Coastguard Worker 	struct fuse_read_in *fri = (struct fuse_read_in *) inarg;
1722*9e564957SAndroid Build Coastguard Worker 	struct fuse_read_out *fro = (struct fuse_read_out *) (fri + 1);
1723*9e564957SAndroid Build Coastguard Worker 	struct fuse_dirent *dirents = (struct fuse_dirent *) (fro + 1);
1724*9e564957SAndroid Build Coastguard Worker 	struct fuse_file_info fi;
1725*9e564957SAndroid Build Coastguard Worker 
1726*9e564957SAndroid Build Coastguard Worker 	memset(&fi, 0, sizeof(fi));
1727*9e564957SAndroid Build Coastguard Worker 	fi.fh = fri->fh;
1728*9e564957SAndroid Build Coastguard Worker 
1729*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.readdirpostfilter)
1730*9e564957SAndroid Build Coastguard Worker 		req->se->op.readdirpostfilter(req, nodeid, error_in, fri->offset,
1731*9e564957SAndroid Build Coastguard Worker 										fro->offset,
1732*9e564957SAndroid Build Coastguard Worker 										size - sizeof(*fri) - sizeof(*fro),
1733*9e564957SAndroid Build Coastguard Worker 										dirents, &fi);
1734*9e564957SAndroid Build Coastguard Worker 	else
1735*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1736*9e564957SAndroid Build Coastguard Worker }
1737*9e564957SAndroid Build Coastguard Worker 
1738*9e564957SAndroid Build Coastguard Worker static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1739*9e564957SAndroid Build Coastguard Worker {
1740*9e564957SAndroid Build Coastguard Worker 	struct fuse_release_in *arg = (struct fuse_release_in *) inarg;
1741*9e564957SAndroid Build Coastguard Worker 	struct fuse_file_info fi;
1742*9e564957SAndroid Build Coastguard Worker 
1743*9e564957SAndroid Build Coastguard Worker 	memset(&fi, 0, sizeof(fi));
1744*9e564957SAndroid Build Coastguard Worker 	fi.flags = arg->flags;
1745*9e564957SAndroid Build Coastguard Worker 	fi.fh = arg->fh;
1746*9e564957SAndroid Build Coastguard Worker 
1747*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.releasedir)
1748*9e564957SAndroid Build Coastguard Worker 		req->se->op.releasedir(req, nodeid, &fi);
1749*9e564957SAndroid Build Coastguard Worker 	else
1750*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, 0);
1751*9e564957SAndroid Build Coastguard Worker }
1752*9e564957SAndroid Build Coastguard Worker 
1753*9e564957SAndroid Build Coastguard Worker static void do_fsyncdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1754*9e564957SAndroid Build Coastguard Worker {
1755*9e564957SAndroid Build Coastguard Worker 	struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg;
1756*9e564957SAndroid Build Coastguard Worker 	struct fuse_file_info fi;
1757*9e564957SAndroid Build Coastguard Worker 	int datasync = arg->fsync_flags & 1;
1758*9e564957SAndroid Build Coastguard Worker 
1759*9e564957SAndroid Build Coastguard Worker 	memset(&fi, 0, sizeof(fi));
1760*9e564957SAndroid Build Coastguard Worker 	fi.fh = arg->fh;
1761*9e564957SAndroid Build Coastguard Worker 
1762*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.fsyncdir)
1763*9e564957SAndroid Build Coastguard Worker 		req->se->op.fsyncdir(req, nodeid, datasync, &fi);
1764*9e564957SAndroid Build Coastguard Worker 	else
1765*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1766*9e564957SAndroid Build Coastguard Worker }
1767*9e564957SAndroid Build Coastguard Worker 
1768*9e564957SAndroid Build Coastguard Worker static void do_statfs(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1769*9e564957SAndroid Build Coastguard Worker {
1770*9e564957SAndroid Build Coastguard Worker 	(void) nodeid;
1771*9e564957SAndroid Build Coastguard Worker 	(void) inarg;
1772*9e564957SAndroid Build Coastguard Worker 
1773*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.statfs)
1774*9e564957SAndroid Build Coastguard Worker 		req->se->op.statfs(req, nodeid);
1775*9e564957SAndroid Build Coastguard Worker 	else {
1776*9e564957SAndroid Build Coastguard Worker 		struct statvfs buf = {
1777*9e564957SAndroid Build Coastguard Worker 			.f_namemax = 255,
1778*9e564957SAndroid Build Coastguard Worker 			.f_bsize = 512,
1779*9e564957SAndroid Build Coastguard Worker 		};
1780*9e564957SAndroid Build Coastguard Worker 		fuse_reply_statfs(req, &buf);
1781*9e564957SAndroid Build Coastguard Worker 	}
1782*9e564957SAndroid Build Coastguard Worker }
1783*9e564957SAndroid Build Coastguard Worker 
1784*9e564957SAndroid Build Coastguard Worker static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1785*9e564957SAndroid Build Coastguard Worker {
1786*9e564957SAndroid Build Coastguard Worker 	struct fuse_session *se = req->se;
1787*9e564957SAndroid Build Coastguard Worker 	unsigned int xattr_ext = !!(se->conn.want & FUSE_CAP_SETXATTR_EXT);
1788*9e564957SAndroid Build Coastguard Worker 	struct fuse_setxattr_in *arg = (struct fuse_setxattr_in *) inarg;
1789*9e564957SAndroid Build Coastguard Worker 	char *name = xattr_ext ? PARAM(arg) :
1790*9e564957SAndroid Build Coastguard Worker 		     (char *)arg + FUSE_COMPAT_SETXATTR_IN_SIZE;
1791*9e564957SAndroid Build Coastguard Worker 	char *value = name + strlen(name) + 1;
1792*9e564957SAndroid Build Coastguard Worker 
1793*9e564957SAndroid Build Coastguard Worker 	/* XXX:The API should be extended to support extra_flags/setxattr_flags */
1794*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.setxattr)
1795*9e564957SAndroid Build Coastguard Worker 		req->se->op.setxattr(req, nodeid, name, value, arg->size,
1796*9e564957SAndroid Build Coastguard Worker 				    arg->flags);
1797*9e564957SAndroid Build Coastguard Worker 	else
1798*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1799*9e564957SAndroid Build Coastguard Worker }
1800*9e564957SAndroid Build Coastguard Worker 
1801*9e564957SAndroid Build Coastguard Worker static void do_getxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1802*9e564957SAndroid Build Coastguard Worker {
1803*9e564957SAndroid Build Coastguard Worker 	struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg;
1804*9e564957SAndroid Build Coastguard Worker 
1805*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.getxattr)
1806*9e564957SAndroid Build Coastguard Worker 		req->se->op.getxattr(req, nodeid, PARAM(arg), arg->size);
1807*9e564957SAndroid Build Coastguard Worker 	else
1808*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1809*9e564957SAndroid Build Coastguard Worker }
1810*9e564957SAndroid Build Coastguard Worker 
1811*9e564957SAndroid Build Coastguard Worker static void do_listxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1812*9e564957SAndroid Build Coastguard Worker {
1813*9e564957SAndroid Build Coastguard Worker 	struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg;
1814*9e564957SAndroid Build Coastguard Worker 
1815*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.listxattr)
1816*9e564957SAndroid Build Coastguard Worker 		req->se->op.listxattr(req, nodeid, arg->size);
1817*9e564957SAndroid Build Coastguard Worker 	else
1818*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1819*9e564957SAndroid Build Coastguard Worker }
1820*9e564957SAndroid Build Coastguard Worker 
1821*9e564957SAndroid Build Coastguard Worker static void do_removexattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1822*9e564957SAndroid Build Coastguard Worker {
1823*9e564957SAndroid Build Coastguard Worker 	char *name = (char *) inarg;
1824*9e564957SAndroid Build Coastguard Worker 
1825*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.removexattr)
1826*9e564957SAndroid Build Coastguard Worker 		req->se->op.removexattr(req, nodeid, name);
1827*9e564957SAndroid Build Coastguard Worker 	else
1828*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1829*9e564957SAndroid Build Coastguard Worker }
1830*9e564957SAndroid Build Coastguard Worker 
1831*9e564957SAndroid Build Coastguard Worker static void convert_fuse_file_lock(struct fuse_file_lock *fl,
1832*9e564957SAndroid Build Coastguard Worker 				   struct flock *flock)
1833*9e564957SAndroid Build Coastguard Worker {
1834*9e564957SAndroid Build Coastguard Worker 	memset(flock, 0, sizeof(struct flock));
1835*9e564957SAndroid Build Coastguard Worker 	flock->l_type = fl->type;
1836*9e564957SAndroid Build Coastguard Worker 	flock->l_whence = SEEK_SET;
1837*9e564957SAndroid Build Coastguard Worker 	flock->l_start = fl->start;
1838*9e564957SAndroid Build Coastguard Worker 	if (fl->end == OFFSET_MAX)
1839*9e564957SAndroid Build Coastguard Worker 		flock->l_len = 0;
1840*9e564957SAndroid Build Coastguard Worker 	else
1841*9e564957SAndroid Build Coastguard Worker 		flock->l_len = fl->end - fl->start + 1;
1842*9e564957SAndroid Build Coastguard Worker 	flock->l_pid = fl->pid;
1843*9e564957SAndroid Build Coastguard Worker }
1844*9e564957SAndroid Build Coastguard Worker 
1845*9e564957SAndroid Build Coastguard Worker static void do_getlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1846*9e564957SAndroid Build Coastguard Worker {
1847*9e564957SAndroid Build Coastguard Worker 	struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg;
1848*9e564957SAndroid Build Coastguard Worker 	struct fuse_file_info fi;
1849*9e564957SAndroid Build Coastguard Worker 	struct flock flock;
1850*9e564957SAndroid Build Coastguard Worker 
1851*9e564957SAndroid Build Coastguard Worker 	memset(&fi, 0, sizeof(fi));
1852*9e564957SAndroid Build Coastguard Worker 	fi.fh = arg->fh;
1853*9e564957SAndroid Build Coastguard Worker 	fi.lock_owner = arg->owner;
1854*9e564957SAndroid Build Coastguard Worker 
1855*9e564957SAndroid Build Coastguard Worker 	convert_fuse_file_lock(&arg->lk, &flock);
1856*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.getlk)
1857*9e564957SAndroid Build Coastguard Worker 		req->se->op.getlk(req, nodeid, &fi, &flock);
1858*9e564957SAndroid Build Coastguard Worker 	else
1859*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
1860*9e564957SAndroid Build Coastguard Worker }
1861*9e564957SAndroid Build Coastguard Worker 
1862*9e564957SAndroid Build Coastguard Worker static void do_setlk_common(fuse_req_t req, fuse_ino_t nodeid,
1863*9e564957SAndroid Build Coastguard Worker 			    const void *inarg, int sleep)
1864*9e564957SAndroid Build Coastguard Worker {
1865*9e564957SAndroid Build Coastguard Worker 	struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg;
1866*9e564957SAndroid Build Coastguard Worker 	struct fuse_file_info fi;
1867*9e564957SAndroid Build Coastguard Worker 	struct flock flock;
1868*9e564957SAndroid Build Coastguard Worker 
1869*9e564957SAndroid Build Coastguard Worker 	memset(&fi, 0, sizeof(fi));
1870*9e564957SAndroid Build Coastguard Worker 	fi.fh = arg->fh;
1871*9e564957SAndroid Build Coastguard Worker 	fi.lock_owner = arg->owner;
1872*9e564957SAndroid Build Coastguard Worker 
1873*9e564957SAndroid Build Coastguard Worker 	if (arg->lk_flags & FUSE_LK_FLOCK) {
1874*9e564957SAndroid Build Coastguard Worker 		int op = 0;
1875*9e564957SAndroid Build Coastguard Worker 
1876*9e564957SAndroid Build Coastguard Worker 		switch (arg->lk.type) {
1877*9e564957SAndroid Build Coastguard Worker 		case F_RDLCK:
1878*9e564957SAndroid Build Coastguard Worker 			op = LOCK_SH;
1879*9e564957SAndroid Build Coastguard Worker 			break;
1880*9e564957SAndroid Build Coastguard Worker 		case F_WRLCK:
1881*9e564957SAndroid Build Coastguard Worker 			op = LOCK_EX;
1882*9e564957SAndroid Build Coastguard Worker 			break;
1883*9e564957SAndroid Build Coastguard Worker 		case F_UNLCK:
1884*9e564957SAndroid Build Coastguard Worker 			op = LOCK_UN;
1885*9e564957SAndroid Build Coastguard Worker 			break;
1886*9e564957SAndroid Build Coastguard Worker 		}
1887*9e564957SAndroid Build Coastguard Worker 		if (!sleep)
1888*9e564957SAndroid Build Coastguard Worker 			op |= LOCK_NB;
1889*9e564957SAndroid Build Coastguard Worker 
1890*9e564957SAndroid Build Coastguard Worker 		if (req->se->op.flock)
1891*9e564957SAndroid Build Coastguard Worker 			req->se->op.flock(req, nodeid, &fi, op);
1892*9e564957SAndroid Build Coastguard Worker 		else
1893*9e564957SAndroid Build Coastguard Worker 			fuse_reply_err(req, ENOSYS);
1894*9e564957SAndroid Build Coastguard Worker 	} else {
1895*9e564957SAndroid Build Coastguard Worker 		convert_fuse_file_lock(&arg->lk, &flock);
1896*9e564957SAndroid Build Coastguard Worker 		if (req->se->op.setlk)
1897*9e564957SAndroid Build Coastguard Worker 			req->se->op.setlk(req, nodeid, &fi, &flock, sleep);
1898*9e564957SAndroid Build Coastguard Worker 		else
1899*9e564957SAndroid Build Coastguard Worker 			fuse_reply_err(req, ENOSYS);
1900*9e564957SAndroid Build Coastguard Worker 	}
1901*9e564957SAndroid Build Coastguard Worker }
1902*9e564957SAndroid Build Coastguard Worker 
1903*9e564957SAndroid Build Coastguard Worker static void do_setlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1904*9e564957SAndroid Build Coastguard Worker {
1905*9e564957SAndroid Build Coastguard Worker 	do_setlk_common(req, nodeid, inarg, 0);
1906*9e564957SAndroid Build Coastguard Worker }
1907*9e564957SAndroid Build Coastguard Worker 
1908*9e564957SAndroid Build Coastguard Worker static void do_setlkw(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1909*9e564957SAndroid Build Coastguard Worker {
1910*9e564957SAndroid Build Coastguard Worker 	do_setlk_common(req, nodeid, inarg, 1);
1911*9e564957SAndroid Build Coastguard Worker }
1912*9e564957SAndroid Build Coastguard Worker 
1913*9e564957SAndroid Build Coastguard Worker static int find_interrupted(struct fuse_session *se, struct fuse_req *req)
1914*9e564957SAndroid Build Coastguard Worker {
1915*9e564957SAndroid Build Coastguard Worker 	struct fuse_req *curr;
1916*9e564957SAndroid Build Coastguard Worker 
1917*9e564957SAndroid Build Coastguard Worker 	for (curr = se->list.next; curr != &se->list; curr = curr->next) {
1918*9e564957SAndroid Build Coastguard Worker 		if (curr->unique == req->u.i.unique) {
1919*9e564957SAndroid Build Coastguard Worker 			fuse_interrupt_func_t func;
1920*9e564957SAndroid Build Coastguard Worker 			void *data;
1921*9e564957SAndroid Build Coastguard Worker 
1922*9e564957SAndroid Build Coastguard Worker 			curr->ctr++;
1923*9e564957SAndroid Build Coastguard Worker 			pthread_mutex_unlock(&se->lock);
1924*9e564957SAndroid Build Coastguard Worker 
1925*9e564957SAndroid Build Coastguard Worker 			/* Ugh, ugly locking */
1926*9e564957SAndroid Build Coastguard Worker 			pthread_mutex_lock(&curr->lock);
1927*9e564957SAndroid Build Coastguard Worker 			pthread_mutex_lock(&se->lock);
1928*9e564957SAndroid Build Coastguard Worker 			curr->interrupted = 1;
1929*9e564957SAndroid Build Coastguard Worker 			func = curr->u.ni.func;
1930*9e564957SAndroid Build Coastguard Worker 			data = curr->u.ni.data;
1931*9e564957SAndroid Build Coastguard Worker 			pthread_mutex_unlock(&se->lock);
1932*9e564957SAndroid Build Coastguard Worker 			if (func)
1933*9e564957SAndroid Build Coastguard Worker 				func(curr, data);
1934*9e564957SAndroid Build Coastguard Worker 			pthread_mutex_unlock(&curr->lock);
1935*9e564957SAndroid Build Coastguard Worker 
1936*9e564957SAndroid Build Coastguard Worker 			pthread_mutex_lock(&se->lock);
1937*9e564957SAndroid Build Coastguard Worker 			curr->ctr--;
1938*9e564957SAndroid Build Coastguard Worker 			if (!curr->ctr) {
1939*9e564957SAndroid Build Coastguard Worker 				destroy_req(curr);
1940*9e564957SAndroid Build Coastguard Worker 			}
1941*9e564957SAndroid Build Coastguard Worker 
1942*9e564957SAndroid Build Coastguard Worker 			return 1;
1943*9e564957SAndroid Build Coastguard Worker 		}
1944*9e564957SAndroid Build Coastguard Worker 	}
1945*9e564957SAndroid Build Coastguard Worker 	for (curr = se->interrupts.next; curr != &se->interrupts;
1946*9e564957SAndroid Build Coastguard Worker 	     curr = curr->next) {
1947*9e564957SAndroid Build Coastguard Worker 		if (curr->u.i.unique == req->u.i.unique)
1948*9e564957SAndroid Build Coastguard Worker 			return 1;
1949*9e564957SAndroid Build Coastguard Worker 	}
1950*9e564957SAndroid Build Coastguard Worker 	return 0;
1951*9e564957SAndroid Build Coastguard Worker }
1952*9e564957SAndroid Build Coastguard Worker 
1953*9e564957SAndroid Build Coastguard Worker static void do_interrupt(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
1954*9e564957SAndroid Build Coastguard Worker {
1955*9e564957SAndroid Build Coastguard Worker 	struct fuse_interrupt_in *arg = (struct fuse_interrupt_in *) inarg;
1956*9e564957SAndroid Build Coastguard Worker 	struct fuse_session *se = req->se;
1957*9e564957SAndroid Build Coastguard Worker 
1958*9e564957SAndroid Build Coastguard Worker 	(void) nodeid;
1959*9e564957SAndroid Build Coastguard Worker 	if (se->debug)
1960*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_DEBUG, "INTERRUPT: %llu\n",
1961*9e564957SAndroid Build Coastguard Worker 			(unsigned long long) arg->unique);
1962*9e564957SAndroid Build Coastguard Worker 
1963*9e564957SAndroid Build Coastguard Worker 	req->u.i.unique = arg->unique;
1964*9e564957SAndroid Build Coastguard Worker 
1965*9e564957SAndroid Build Coastguard Worker 	pthread_mutex_lock(&se->lock);
1966*9e564957SAndroid Build Coastguard Worker 	if (find_interrupted(se, req)) {
1967*9e564957SAndroid Build Coastguard Worker 		fuse_chan_put(req->ch);
1968*9e564957SAndroid Build Coastguard Worker 		req->ch = NULL;
1969*9e564957SAndroid Build Coastguard Worker 		destroy_req(req);
1970*9e564957SAndroid Build Coastguard Worker 	} else
1971*9e564957SAndroid Build Coastguard Worker 		list_add_req(req, &se->interrupts);
1972*9e564957SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&se->lock);
1973*9e564957SAndroid Build Coastguard Worker }
1974*9e564957SAndroid Build Coastguard Worker 
1975*9e564957SAndroid Build Coastguard Worker static struct fuse_req *check_interrupt(struct fuse_session *se,
1976*9e564957SAndroid Build Coastguard Worker 					struct fuse_req *req)
1977*9e564957SAndroid Build Coastguard Worker {
1978*9e564957SAndroid Build Coastguard Worker 	struct fuse_req *curr;
1979*9e564957SAndroid Build Coastguard Worker 
1980*9e564957SAndroid Build Coastguard Worker 	for (curr = se->interrupts.next; curr != &se->interrupts;
1981*9e564957SAndroid Build Coastguard Worker 	     curr = curr->next) {
1982*9e564957SAndroid Build Coastguard Worker 		if (curr->u.i.unique == req->unique) {
1983*9e564957SAndroid Build Coastguard Worker 			req->interrupted = 1;
1984*9e564957SAndroid Build Coastguard Worker 			list_del_req(curr);
1985*9e564957SAndroid Build Coastguard Worker 			fuse_chan_put(curr->ch);
1986*9e564957SAndroid Build Coastguard Worker 			curr->ch = NULL;
1987*9e564957SAndroid Build Coastguard Worker 			destroy_req(curr);
1988*9e564957SAndroid Build Coastguard Worker 			return NULL;
1989*9e564957SAndroid Build Coastguard Worker 		}
1990*9e564957SAndroid Build Coastguard Worker 	}
1991*9e564957SAndroid Build Coastguard Worker 	curr = se->interrupts.next;
1992*9e564957SAndroid Build Coastguard Worker 	if (curr != &se->interrupts) {
1993*9e564957SAndroid Build Coastguard Worker 		list_del_req(curr);
1994*9e564957SAndroid Build Coastguard Worker 		list_init_req(curr);
1995*9e564957SAndroid Build Coastguard Worker 		return curr;
1996*9e564957SAndroid Build Coastguard Worker 	} else
1997*9e564957SAndroid Build Coastguard Worker 		return NULL;
1998*9e564957SAndroid Build Coastguard Worker }
1999*9e564957SAndroid Build Coastguard Worker 
2000*9e564957SAndroid Build Coastguard Worker static void do_bmap(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
2001*9e564957SAndroid Build Coastguard Worker {
2002*9e564957SAndroid Build Coastguard Worker 	struct fuse_bmap_in *arg = (struct fuse_bmap_in *) inarg;
2003*9e564957SAndroid Build Coastguard Worker 
2004*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.bmap)
2005*9e564957SAndroid Build Coastguard Worker 		req->se->op.bmap(req, nodeid, arg->blocksize, arg->block);
2006*9e564957SAndroid Build Coastguard Worker 	else
2007*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
2008*9e564957SAndroid Build Coastguard Worker }
2009*9e564957SAndroid Build Coastguard Worker 
2010*9e564957SAndroid Build Coastguard Worker static void do_ioctl(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
2011*9e564957SAndroid Build Coastguard Worker {
2012*9e564957SAndroid Build Coastguard Worker 	struct fuse_ioctl_in *arg = (struct fuse_ioctl_in *) inarg;
2013*9e564957SAndroid Build Coastguard Worker 	unsigned int flags = arg->flags;
2014*9e564957SAndroid Build Coastguard Worker 	void *in_buf = arg->in_size ? PARAM(arg) : NULL;
2015*9e564957SAndroid Build Coastguard Worker 	struct fuse_file_info fi;
2016*9e564957SAndroid Build Coastguard Worker 
2017*9e564957SAndroid Build Coastguard Worker 	if (flags & FUSE_IOCTL_DIR &&
2018*9e564957SAndroid Build Coastguard Worker 	    !(req->se->conn.want & FUSE_CAP_IOCTL_DIR)) {
2019*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOTTY);
2020*9e564957SAndroid Build Coastguard Worker 		return;
2021*9e564957SAndroid Build Coastguard Worker 	}
2022*9e564957SAndroid Build Coastguard Worker 
2023*9e564957SAndroid Build Coastguard Worker 	memset(&fi, 0, sizeof(fi));
2024*9e564957SAndroid Build Coastguard Worker 	fi.fh = arg->fh;
2025*9e564957SAndroid Build Coastguard Worker 
2026*9e564957SAndroid Build Coastguard Worker 	if (sizeof(void *) == 4 && req->se->conn.proto_minor >= 16 &&
2027*9e564957SAndroid Build Coastguard Worker 	    !(flags & FUSE_IOCTL_32BIT)) {
2028*9e564957SAndroid Build Coastguard Worker 		req->ioctl_64bit = 1;
2029*9e564957SAndroid Build Coastguard Worker 	}
2030*9e564957SAndroid Build Coastguard Worker 
2031*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.ioctl)
2032*9e564957SAndroid Build Coastguard Worker 		req->se->op.ioctl(req, nodeid, arg->cmd,
2033*9e564957SAndroid Build Coastguard Worker 				 (void *)(uintptr_t)arg->arg, &fi, flags,
2034*9e564957SAndroid Build Coastguard Worker 				 in_buf, arg->in_size, arg->out_size);
2035*9e564957SAndroid Build Coastguard Worker 	else
2036*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
2037*9e564957SAndroid Build Coastguard Worker }
2038*9e564957SAndroid Build Coastguard Worker 
2039*9e564957SAndroid Build Coastguard Worker void fuse_pollhandle_destroy(struct fuse_pollhandle *ph)
2040*9e564957SAndroid Build Coastguard Worker {
2041*9e564957SAndroid Build Coastguard Worker 	free(ph);
2042*9e564957SAndroid Build Coastguard Worker }
2043*9e564957SAndroid Build Coastguard Worker 
2044*9e564957SAndroid Build Coastguard Worker static void do_poll(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
2045*9e564957SAndroid Build Coastguard Worker {
2046*9e564957SAndroid Build Coastguard Worker 	struct fuse_poll_in *arg = (struct fuse_poll_in *) inarg;
2047*9e564957SAndroid Build Coastguard Worker 	struct fuse_file_info fi;
2048*9e564957SAndroid Build Coastguard Worker 
2049*9e564957SAndroid Build Coastguard Worker 	memset(&fi, 0, sizeof(fi));
2050*9e564957SAndroid Build Coastguard Worker 	fi.fh = arg->fh;
2051*9e564957SAndroid Build Coastguard Worker 	fi.poll_events = arg->events;
2052*9e564957SAndroid Build Coastguard Worker 
2053*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.poll) {
2054*9e564957SAndroid Build Coastguard Worker 		struct fuse_pollhandle *ph = NULL;
2055*9e564957SAndroid Build Coastguard Worker 
2056*9e564957SAndroid Build Coastguard Worker 		if (arg->flags & FUSE_POLL_SCHEDULE_NOTIFY) {
2057*9e564957SAndroid Build Coastguard Worker 			ph = malloc(sizeof(struct fuse_pollhandle));
2058*9e564957SAndroid Build Coastguard Worker 			if (ph == NULL) {
2059*9e564957SAndroid Build Coastguard Worker 				fuse_reply_err(req, ENOMEM);
2060*9e564957SAndroid Build Coastguard Worker 				return;
2061*9e564957SAndroid Build Coastguard Worker 			}
2062*9e564957SAndroid Build Coastguard Worker 			ph->kh = arg->kh;
2063*9e564957SAndroid Build Coastguard Worker 			ph->se = req->se;
2064*9e564957SAndroid Build Coastguard Worker 		}
2065*9e564957SAndroid Build Coastguard Worker 
2066*9e564957SAndroid Build Coastguard Worker 		req->se->op.poll(req, nodeid, &fi, ph);
2067*9e564957SAndroid Build Coastguard Worker 	} else {
2068*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
2069*9e564957SAndroid Build Coastguard Worker 	}
2070*9e564957SAndroid Build Coastguard Worker }
2071*9e564957SAndroid Build Coastguard Worker 
2072*9e564957SAndroid Build Coastguard Worker static void do_fallocate(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
2073*9e564957SAndroid Build Coastguard Worker {
2074*9e564957SAndroid Build Coastguard Worker 	struct fuse_fallocate_in *arg = (struct fuse_fallocate_in *) inarg;
2075*9e564957SAndroid Build Coastguard Worker 	struct fuse_file_info fi;
2076*9e564957SAndroid Build Coastguard Worker 
2077*9e564957SAndroid Build Coastguard Worker 	memset(&fi, 0, sizeof(fi));
2078*9e564957SAndroid Build Coastguard Worker 	fi.fh = arg->fh;
2079*9e564957SAndroid Build Coastguard Worker 
2080*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.fallocate)
2081*9e564957SAndroid Build Coastguard Worker 		req->se->op.fallocate(req, nodeid, arg->mode, arg->offset, arg->length, &fi);
2082*9e564957SAndroid Build Coastguard Worker 	else
2083*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
2084*9e564957SAndroid Build Coastguard Worker }
2085*9e564957SAndroid Build Coastguard Worker 
2086*9e564957SAndroid Build Coastguard Worker static void do_copy_file_range(fuse_req_t req, fuse_ino_t nodeid_in, const void *inarg)
2087*9e564957SAndroid Build Coastguard Worker {
2088*9e564957SAndroid Build Coastguard Worker 	struct fuse_copy_file_range_in *arg = (struct fuse_copy_file_range_in *) inarg;
2089*9e564957SAndroid Build Coastguard Worker 	struct fuse_file_info fi_in, fi_out;
2090*9e564957SAndroid Build Coastguard Worker 
2091*9e564957SAndroid Build Coastguard Worker 	memset(&fi_in, 0, sizeof(fi_in));
2092*9e564957SAndroid Build Coastguard Worker 	fi_in.fh = arg->fh_in;
2093*9e564957SAndroid Build Coastguard Worker 
2094*9e564957SAndroid Build Coastguard Worker 	memset(&fi_out, 0, sizeof(fi_out));
2095*9e564957SAndroid Build Coastguard Worker 	fi_out.fh = arg->fh_out;
2096*9e564957SAndroid Build Coastguard Worker 
2097*9e564957SAndroid Build Coastguard Worker 
2098*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.copy_file_range)
2099*9e564957SAndroid Build Coastguard Worker 		req->se->op.copy_file_range(req, nodeid_in, arg->off_in,
2100*9e564957SAndroid Build Coastguard Worker 					    &fi_in, arg->nodeid_out,
2101*9e564957SAndroid Build Coastguard Worker 					    arg->off_out, &fi_out, arg->len,
2102*9e564957SAndroid Build Coastguard Worker 					    arg->flags);
2103*9e564957SAndroid Build Coastguard Worker 	else
2104*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
2105*9e564957SAndroid Build Coastguard Worker }
2106*9e564957SAndroid Build Coastguard Worker 
2107*9e564957SAndroid Build Coastguard Worker static void do_lseek(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
2108*9e564957SAndroid Build Coastguard Worker {
2109*9e564957SAndroid Build Coastguard Worker 	struct fuse_lseek_in *arg = (struct fuse_lseek_in *) inarg;
2110*9e564957SAndroid Build Coastguard Worker 	struct fuse_file_info fi;
2111*9e564957SAndroid Build Coastguard Worker 
2112*9e564957SAndroid Build Coastguard Worker 	memset(&fi, 0, sizeof(fi));
2113*9e564957SAndroid Build Coastguard Worker 	fi.fh = arg->fh;
2114*9e564957SAndroid Build Coastguard Worker 
2115*9e564957SAndroid Build Coastguard Worker 	if (req->se->op.lseek)
2116*9e564957SAndroid Build Coastguard Worker 		req->se->op.lseek(req, nodeid, arg->offset, arg->whence, &fi);
2117*9e564957SAndroid Build Coastguard Worker 	else
2118*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, ENOSYS);
2119*9e564957SAndroid Build Coastguard Worker }
2120*9e564957SAndroid Build Coastguard Worker 
2121*9e564957SAndroid Build Coastguard Worker /* Prevent bogus data races (bogus since "init" is called before
2122*9e564957SAndroid Build Coastguard Worker  * multi-threading becomes relevant */
2123*9e564957SAndroid Build Coastguard Worker static __attribute__((no_sanitize("thread")))
2124*9e564957SAndroid Build Coastguard Worker void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
2125*9e564957SAndroid Build Coastguard Worker {
2126*9e564957SAndroid Build Coastguard Worker 	struct fuse_init_in *arg = (struct fuse_init_in *) inarg;
2127*9e564957SAndroid Build Coastguard Worker 	struct fuse_init_out outarg;
2128*9e564957SAndroid Build Coastguard Worker 	struct fuse_session *se = req->se;
2129*9e564957SAndroid Build Coastguard Worker 	size_t bufsize = se->bufsize;
2130*9e564957SAndroid Build Coastguard Worker 	size_t outargsize = sizeof(outarg);
2131*9e564957SAndroid Build Coastguard Worker 	uint64_t inargflags = 0;
2132*9e564957SAndroid Build Coastguard Worker 	uint64_t outargflags = 0;
2133*9e564957SAndroid Build Coastguard Worker 	(void) nodeid;
2134*9e564957SAndroid Build Coastguard Worker 	if (se->debug) {
2135*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_DEBUG, "INIT: %u.%u\n", arg->major, arg->minor);
2136*9e564957SAndroid Build Coastguard Worker 		if (arg->major == 7 && arg->minor >= 6) {
2137*9e564957SAndroid Build Coastguard Worker 			fuse_log(FUSE_LOG_DEBUG, "flags=0x%08x\n", arg->flags);
2138*9e564957SAndroid Build Coastguard Worker 			fuse_log(FUSE_LOG_DEBUG, "max_readahead=0x%08x\n",
2139*9e564957SAndroid Build Coastguard Worker 				arg->max_readahead);
2140*9e564957SAndroid Build Coastguard Worker 		}
2141*9e564957SAndroid Build Coastguard Worker 	}
2142*9e564957SAndroid Build Coastguard Worker 	se->conn.proto_major = arg->major;
2143*9e564957SAndroid Build Coastguard Worker 	se->conn.proto_minor = arg->minor;
2144*9e564957SAndroid Build Coastguard Worker 	se->conn.capable = 0;
2145*9e564957SAndroid Build Coastguard Worker 	se->conn.want = 0;
2146*9e564957SAndroid Build Coastguard Worker 
2147*9e564957SAndroid Build Coastguard Worker 	memset(&outarg, 0, sizeof(outarg));
2148*9e564957SAndroid Build Coastguard Worker 	outarg.major = FUSE_KERNEL_VERSION;
2149*9e564957SAndroid Build Coastguard Worker 	outarg.minor = FUSE_KERNEL_MINOR_VERSION;
2150*9e564957SAndroid Build Coastguard Worker 
2151*9e564957SAndroid Build Coastguard Worker 	if (arg->major < 7) {
2152*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: unsupported protocol version: %u.%u\n",
2153*9e564957SAndroid Build Coastguard Worker 			arg->major, arg->minor);
2154*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, EPROTO);
2155*9e564957SAndroid Build Coastguard Worker 		return;
2156*9e564957SAndroid Build Coastguard Worker 	}
2157*9e564957SAndroid Build Coastguard Worker 
2158*9e564957SAndroid Build Coastguard Worker 	if (arg->major > 7) {
2159*9e564957SAndroid Build Coastguard Worker 		/* Wait for a second INIT request with a 7.X version */
2160*9e564957SAndroid Build Coastguard Worker 		send_reply_ok(req, &outarg, sizeof(outarg));
2161*9e564957SAndroid Build Coastguard Worker 		return;
2162*9e564957SAndroid Build Coastguard Worker 	}
2163*9e564957SAndroid Build Coastguard Worker 
2164*9e564957SAndroid Build Coastguard Worker 	if (arg->minor >= 6) {
2165*9e564957SAndroid Build Coastguard Worker 		if (arg->max_readahead < se->conn.max_readahead)
2166*9e564957SAndroid Build Coastguard Worker 			se->conn.max_readahead = arg->max_readahead;
2167*9e564957SAndroid Build Coastguard Worker 		inargflags = arg->flags;
2168*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_INIT_EXT)
2169*9e564957SAndroid Build Coastguard Worker 			inargflags = inargflags | (uint64_t) arg->flags2 << 32;
2170*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_ASYNC_READ)
2171*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_ASYNC_READ;
2172*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_POSIX_LOCKS)
2173*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_POSIX_LOCKS;
2174*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_ATOMIC_O_TRUNC)
2175*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_ATOMIC_O_TRUNC;
2176*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_EXPORT_SUPPORT)
2177*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_EXPORT_SUPPORT;
2178*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_DONT_MASK)
2179*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_DONT_MASK;
2180*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_FLOCK_LOCKS)
2181*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_FLOCK_LOCKS;
2182*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_AUTO_INVAL_DATA)
2183*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_AUTO_INVAL_DATA;
2184*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_DO_READDIRPLUS)
2185*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_READDIRPLUS;
2186*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_READDIRPLUS_AUTO)
2187*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_READDIRPLUS_AUTO;
2188*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_ASYNC_DIO)
2189*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_ASYNC_DIO;
2190*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_WRITEBACK_CACHE)
2191*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_WRITEBACK_CACHE;
2192*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_NO_OPEN_SUPPORT)
2193*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_NO_OPEN_SUPPORT;
2194*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_PARALLEL_DIROPS)
2195*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_PARALLEL_DIROPS;
2196*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_POSIX_ACL)
2197*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_POSIX_ACL;
2198*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_HANDLE_KILLPRIV)
2199*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_HANDLE_KILLPRIV;
2200*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_HANDLE_KILLPRIV_V2)
2201*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_HANDLE_KILLPRIV_V2;
2202*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_CACHE_SYMLINKS)
2203*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_CACHE_SYMLINKS;
2204*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_NO_OPENDIR_SUPPORT)
2205*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_NO_OPENDIR_SUPPORT;
2206*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_EXPLICIT_INVAL_DATA)
2207*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_EXPLICIT_INVAL_DATA;
2208*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_SETXATTR_EXT)
2209*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_SETXATTR_EXT;
2210*9e564957SAndroid Build Coastguard Worker 		if (!(inargflags & FUSE_MAX_PAGES)) {
2211*9e564957SAndroid Build Coastguard Worker 			size_t max_bufsize =
2212*9e564957SAndroid Build Coastguard Worker 				FUSE_DEFAULT_MAX_PAGES_PER_REQ * getpagesize()
2213*9e564957SAndroid Build Coastguard Worker 				+ FUSE_BUFFER_HEADER_SIZE;
2214*9e564957SAndroid Build Coastguard Worker 			if (bufsize > max_bufsize) {
2215*9e564957SAndroid Build Coastguard Worker 				bufsize = max_bufsize;
2216*9e564957SAndroid Build Coastguard Worker 			}
2217*9e564957SAndroid Build Coastguard Worker 		}
2218*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_DIRECT_IO_ALLOW_MMAP)
2219*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_DIRECT_IO_ALLOW_MMAP;
2220*9e564957SAndroid Build Coastguard Worker 		if (arg->minor >= 38 || (inargflags & FUSE_HAS_EXPIRE_ONLY))
2221*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_EXPIRE_ONLY;
2222*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_PASSTHROUGH_UPSTREAM)
2223*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_PASSTHROUGH_UPSTREAM;
2224*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_INIT_EXT) {
2225*9e564957SAndroid Build Coastguard Worker 			if (inargflags & (1ULL << 63))
2226*9e564957SAndroid Build Coastguard Worker 				se->conn.capable |= FUSE_CAP_PASSTHROUGH;
2227*9e564957SAndroid Build Coastguard Worker 		} else {
2228*9e564957SAndroid Build Coastguard Worker 			if (inargflags & (1 << 31))
2229*9e564957SAndroid Build Coastguard Worker 				se->conn.capable |= FUSE_CAP_PASSTHROUGH;
2230*9e564957SAndroid Build Coastguard Worker 		}
2231*9e564957SAndroid Build Coastguard Worker 	} else {
2232*9e564957SAndroid Build Coastguard Worker 		se->conn.max_readahead = 0;
2233*9e564957SAndroid Build Coastguard Worker 	}
2234*9e564957SAndroid Build Coastguard Worker 
2235*9e564957SAndroid Build Coastguard Worker 	if (se->conn.proto_minor >= 14) {
2236*9e564957SAndroid Build Coastguard Worker #ifdef HAVE_SPLICE
2237*9e564957SAndroid Build Coastguard Worker #ifdef HAVE_VMSPLICE
2238*9e564957SAndroid Build Coastguard Worker 		if ((se->io == NULL) || (se->io->splice_send != NULL)) {
2239*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_SPLICE_WRITE | FUSE_CAP_SPLICE_MOVE;
2240*9e564957SAndroid Build Coastguard Worker 		}
2241*9e564957SAndroid Build Coastguard Worker #endif
2242*9e564957SAndroid Build Coastguard Worker 		if ((se->io == NULL) || (se->io->splice_receive != NULL)) {
2243*9e564957SAndroid Build Coastguard Worker 			se->conn.capable |= FUSE_CAP_SPLICE_READ;
2244*9e564957SAndroid Build Coastguard Worker 		}
2245*9e564957SAndroid Build Coastguard Worker #endif
2246*9e564957SAndroid Build Coastguard Worker 	}
2247*9e564957SAndroid Build Coastguard Worker 	if (se->conn.proto_minor >= 18)
2248*9e564957SAndroid Build Coastguard Worker 		se->conn.capable |= FUSE_CAP_IOCTL_DIR;
2249*9e564957SAndroid Build Coastguard Worker 
2250*9e564957SAndroid Build Coastguard Worker 	/* Default settings for modern filesystems.
2251*9e564957SAndroid Build Coastguard Worker 	 *
2252*9e564957SAndroid Build Coastguard Worker 	 * Most of these capabilities were disabled by default in
2253*9e564957SAndroid Build Coastguard Worker 	 * libfuse2 for backwards compatibility reasons. In libfuse3,
2254*9e564957SAndroid Build Coastguard Worker 	 * we can finally enable them by default (as long as they're
2255*9e564957SAndroid Build Coastguard Worker 	 * supported by the kernel).
2256*9e564957SAndroid Build Coastguard Worker 	 */
2257*9e564957SAndroid Build Coastguard Worker #define LL_SET_DEFAULT(cond, cap) \
2258*9e564957SAndroid Build Coastguard Worker 	if ((cond) && (se->conn.capable & (cap))) \
2259*9e564957SAndroid Build Coastguard Worker 		se->conn.want |= (cap)
2260*9e564957SAndroid Build Coastguard Worker 	LL_SET_DEFAULT(1, FUSE_CAP_ASYNC_READ);
2261*9e564957SAndroid Build Coastguard Worker 	LL_SET_DEFAULT(1, FUSE_CAP_AUTO_INVAL_DATA);
2262*9e564957SAndroid Build Coastguard Worker 	LL_SET_DEFAULT(1, FUSE_CAP_ASYNC_DIO);
2263*9e564957SAndroid Build Coastguard Worker 	LL_SET_DEFAULT(1, FUSE_CAP_IOCTL_DIR);
2264*9e564957SAndroid Build Coastguard Worker 	LL_SET_DEFAULT(1, FUSE_CAP_ATOMIC_O_TRUNC);
2265*9e564957SAndroid Build Coastguard Worker 	LL_SET_DEFAULT(se->op.write_buf, FUSE_CAP_SPLICE_READ);
2266*9e564957SAndroid Build Coastguard Worker 	LL_SET_DEFAULT(se->op.getlk && se->op.setlk,
2267*9e564957SAndroid Build Coastguard Worker 		       FUSE_CAP_POSIX_LOCKS);
2268*9e564957SAndroid Build Coastguard Worker 	LL_SET_DEFAULT(se->op.flock, FUSE_CAP_FLOCK_LOCKS);
2269*9e564957SAndroid Build Coastguard Worker 	LL_SET_DEFAULT(se->op.readdirplus, FUSE_CAP_READDIRPLUS);
2270*9e564957SAndroid Build Coastguard Worker 	LL_SET_DEFAULT(se->op.readdirplus && se->op.readdir,
2271*9e564957SAndroid Build Coastguard Worker 		       FUSE_CAP_READDIRPLUS_AUTO);
2272*9e564957SAndroid Build Coastguard Worker 
2273*9e564957SAndroid Build Coastguard Worker 	/* This could safely become default, but libfuse needs an API extension
2274*9e564957SAndroid Build Coastguard Worker 	 * to support it
2275*9e564957SAndroid Build Coastguard Worker 	 * LL_SET_DEFAULT(1, FUSE_CAP_SETXATTR_EXT);
2276*9e564957SAndroid Build Coastguard Worker 	 */
2277*9e564957SAndroid Build Coastguard Worker 
2278*9e564957SAndroid Build Coastguard Worker 	se->conn.time_gran = 1;
2279*9e564957SAndroid Build Coastguard Worker 
2280*9e564957SAndroid Build Coastguard Worker 	if (bufsize < FUSE_MIN_READ_BUFFER) {
2281*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: warning: buffer size too small: %zu\n",
2282*9e564957SAndroid Build Coastguard Worker 			bufsize);
2283*9e564957SAndroid Build Coastguard Worker 		bufsize = FUSE_MIN_READ_BUFFER;
2284*9e564957SAndroid Build Coastguard Worker 	}
2285*9e564957SAndroid Build Coastguard Worker 	se->bufsize = bufsize;
2286*9e564957SAndroid Build Coastguard Worker 
2287*9e564957SAndroid Build Coastguard Worker 	se->got_init = 1;
2288*9e564957SAndroid Build Coastguard Worker 	if (se->op.init)
2289*9e564957SAndroid Build Coastguard Worker 		se->op.init(se->userdata, &se->conn);
2290*9e564957SAndroid Build Coastguard Worker 
2291*9e564957SAndroid Build Coastguard Worker 	if (se->conn.max_write > bufsize - FUSE_BUFFER_HEADER_SIZE)
2292*9e564957SAndroid Build Coastguard Worker 		se->conn.max_write = bufsize - FUSE_BUFFER_HEADER_SIZE;
2293*9e564957SAndroid Build Coastguard Worker 
2294*9e564957SAndroid Build Coastguard Worker 	if (se->conn.want & (~se->conn.capable)) {
2295*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: error: filesystem requested capabilities "
2296*9e564957SAndroid Build Coastguard Worker 			"0x%x that are not supported by kernel, aborting.\n",
2297*9e564957SAndroid Build Coastguard Worker 			se->conn.want & (~se->conn.capable));
2298*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, EPROTO);
2299*9e564957SAndroid Build Coastguard Worker 		se->error = -EPROTO;
2300*9e564957SAndroid Build Coastguard Worker 		fuse_session_exit(se);
2301*9e564957SAndroid Build Coastguard Worker 		return;
2302*9e564957SAndroid Build Coastguard Worker 	}
2303*9e564957SAndroid Build Coastguard Worker 
2304*9e564957SAndroid Build Coastguard Worker 	unsigned max_read_mo = get_max_read(se->mo);
2305*9e564957SAndroid Build Coastguard Worker 	if (se->conn.max_read != max_read_mo) {
2306*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: error: init() and fuse_session_new() "
2307*9e564957SAndroid Build Coastguard Worker 			"requested different maximum read size (%u vs %u)\n",
2308*9e564957SAndroid Build Coastguard Worker 			se->conn.max_read, max_read_mo);
2309*9e564957SAndroid Build Coastguard Worker 		fuse_reply_err(req, EPROTO);
2310*9e564957SAndroid Build Coastguard Worker 		se->error = -EPROTO;
2311*9e564957SAndroid Build Coastguard Worker 		fuse_session_exit(se);
2312*9e564957SAndroid Build Coastguard Worker 		return;
2313*9e564957SAndroid Build Coastguard Worker 	}
2314*9e564957SAndroid Build Coastguard Worker 
2315*9e564957SAndroid Build Coastguard Worker 	if (se->conn.max_write < bufsize - FUSE_BUFFER_HEADER_SIZE) {
2316*9e564957SAndroid Build Coastguard Worker 		se->bufsize = se->conn.max_write + FUSE_BUFFER_HEADER_SIZE;
2317*9e564957SAndroid Build Coastguard Worker 	}
2318*9e564957SAndroid Build Coastguard Worker 	if (arg->flags & FUSE_MAX_PAGES) {
2319*9e564957SAndroid Build Coastguard Worker 		outarg.flags |= FUSE_MAX_PAGES;
2320*9e564957SAndroid Build Coastguard Worker 		outarg.max_pages = (se->conn.max_write - 1) / getpagesize() + 1;
2321*9e564957SAndroid Build Coastguard Worker 	}
2322*9e564957SAndroid Build Coastguard Worker 	outargflags = outarg.flags;
2323*9e564957SAndroid Build Coastguard Worker 	/* Always enable big writes, this is superseded
2324*9e564957SAndroid Build Coastguard Worker 	   by the max_write option */
2325*9e564957SAndroid Build Coastguard Worker 	outargflags |= FUSE_BIG_WRITES;
2326*9e564957SAndroid Build Coastguard Worker 
2327*9e564957SAndroid Build Coastguard Worker 	if (se->conn.want & FUSE_CAP_ASYNC_READ)
2328*9e564957SAndroid Build Coastguard Worker 		outargflags |= FUSE_ASYNC_READ;
2329*9e564957SAndroid Build Coastguard Worker 	if (se->conn.want & FUSE_CAP_POSIX_LOCKS)
2330*9e564957SAndroid Build Coastguard Worker 		outargflags |= FUSE_POSIX_LOCKS;
2331*9e564957SAndroid Build Coastguard Worker 	if (se->conn.want & FUSE_CAP_ATOMIC_O_TRUNC)
2332*9e564957SAndroid Build Coastguard Worker 		outargflags |= FUSE_ATOMIC_O_TRUNC;
2333*9e564957SAndroid Build Coastguard Worker 	if (se->conn.want & FUSE_CAP_EXPORT_SUPPORT)
2334*9e564957SAndroid Build Coastguard Worker 		outargflags |= FUSE_EXPORT_SUPPORT;
2335*9e564957SAndroid Build Coastguard Worker 	if (se->conn.want & FUSE_CAP_DONT_MASK)
2336*9e564957SAndroid Build Coastguard Worker 		outargflags |= FUSE_DONT_MASK;
2337*9e564957SAndroid Build Coastguard Worker 	if (se->conn.want & FUSE_CAP_FLOCK_LOCKS)
2338*9e564957SAndroid Build Coastguard Worker 		outargflags |= FUSE_FLOCK_LOCKS;
2339*9e564957SAndroid Build Coastguard Worker 	if (se->conn.want & FUSE_CAP_AUTO_INVAL_DATA)
2340*9e564957SAndroid Build Coastguard Worker 		outargflags |= FUSE_AUTO_INVAL_DATA;
2341*9e564957SAndroid Build Coastguard Worker 	if (se->conn.want & FUSE_CAP_READDIRPLUS)
2342*9e564957SAndroid Build Coastguard Worker 		outargflags |= FUSE_DO_READDIRPLUS;
2343*9e564957SAndroid Build Coastguard Worker 	if (se->conn.want & FUSE_CAP_READDIRPLUS_AUTO)
2344*9e564957SAndroid Build Coastguard Worker 		outargflags |= FUSE_READDIRPLUS_AUTO;
2345*9e564957SAndroid Build Coastguard Worker 	if (se->conn.want & FUSE_CAP_ASYNC_DIO)
2346*9e564957SAndroid Build Coastguard Worker 		outargflags |= FUSE_ASYNC_DIO;
2347*9e564957SAndroid Build Coastguard Worker 	if (se->conn.want & FUSE_CAP_WRITEBACK_CACHE)
2348*9e564957SAndroid Build Coastguard Worker 		outargflags |= FUSE_WRITEBACK_CACHE;
2349*9e564957SAndroid Build Coastguard Worker 	if (se->conn.want & FUSE_CAP_PARALLEL_DIROPS)
2350*9e564957SAndroid Build Coastguard Worker 		outargflags |= FUSE_PARALLEL_DIROPS;
2351*9e564957SAndroid Build Coastguard Worker 	if (se->conn.want & FUSE_CAP_POSIX_ACL)
2352*9e564957SAndroid Build Coastguard Worker 		outargflags |= FUSE_POSIX_ACL;
2353*9e564957SAndroid Build Coastguard Worker 	if (se->conn.want & FUSE_CAP_HANDLE_KILLPRIV)
2354*9e564957SAndroid Build Coastguard Worker 		outargflags |= FUSE_HANDLE_KILLPRIV;
2355*9e564957SAndroid Build Coastguard Worker 	if (se->conn.want & FUSE_CAP_HANDLE_KILLPRIV_V2)
2356*9e564957SAndroid Build Coastguard Worker 		outargflags |= FUSE_HANDLE_KILLPRIV_V2;
2357*9e564957SAndroid Build Coastguard Worker 	if (se->conn.want & FUSE_CAP_CACHE_SYMLINKS)
2358*9e564957SAndroid Build Coastguard Worker 		outargflags |= FUSE_CACHE_SYMLINKS;
2359*9e564957SAndroid Build Coastguard Worker 	if (se->conn.want & FUSE_CAP_EXPLICIT_INVAL_DATA)
2360*9e564957SAndroid Build Coastguard Worker 		outargflags |= FUSE_EXPLICIT_INVAL_DATA;
2361*9e564957SAndroid Build Coastguard Worker 	if (se->conn.want & FUSE_CAP_SETXATTR_EXT)
2362*9e564957SAndroid Build Coastguard Worker 		outargflags |= FUSE_SETXATTR_EXT;
2363*9e564957SAndroid Build Coastguard Worker 	if (se->conn.want & FUSE_CAP_DIRECT_IO_ALLOW_MMAP)
2364*9e564957SAndroid Build Coastguard Worker 		outargflags |= FUSE_DIRECT_IO_ALLOW_MMAP;
2365*9e564957SAndroid Build Coastguard Worker 	if (se->conn.want & FUSE_CAP_PASSTHROUGH_UPSTREAM) {
2366*9e564957SAndroid Build Coastguard Worker 		outargflags |= FUSE_PASSTHROUGH_UPSTREAM;
2367*9e564957SAndroid Build Coastguard Worker 		/*
2368*9e564957SAndroid Build Coastguard Worker 		 * outarg.max_stack_depth includes the fuse stack layer,
2369*9e564957SAndroid Build Coastguard Worker 		 * so it is one more than max_backing_stack_depth.
2370*9e564957SAndroid Build Coastguard Worker 		 */
2371*9e564957SAndroid Build Coastguard Worker 		outarg.max_stack_depth = se->conn.max_backing_stack_depth + 1;
2372*9e564957SAndroid Build Coastguard Worker 	}
2373*9e564957SAndroid Build Coastguard Worker 	if (se->conn.want & FUSE_CAP_PASSTHROUGH) {
2374*9e564957SAndroid Build Coastguard Worker 		if (inargflags & FUSE_INIT_EXT)
2375*9e564957SAndroid Build Coastguard Worker 			outargflags |= (1ULL << 63);
2376*9e564957SAndroid Build Coastguard Worker 		else
2377*9e564957SAndroid Build Coastguard Worker 			outargflags |= (1 << 31);
2378*9e564957SAndroid Build Coastguard Worker 	}
2379*9e564957SAndroid Build Coastguard Worker 	if (inargflags & FUSE_INIT_EXT) {
2380*9e564957SAndroid Build Coastguard Worker 		outargflags |= FUSE_INIT_EXT;
2381*9e564957SAndroid Build Coastguard Worker 		outarg.flags2 = outargflags >> 32;
2382*9e564957SAndroid Build Coastguard Worker 	}
2383*9e564957SAndroid Build Coastguard Worker 
2384*9e564957SAndroid Build Coastguard Worker 	outarg.flags = outargflags;
2385*9e564957SAndroid Build Coastguard Worker 
2386*9e564957SAndroid Build Coastguard Worker 	outarg.max_readahead = se->conn.max_readahead;
2387*9e564957SAndroid Build Coastguard Worker 	outarg.max_write = se->conn.max_write;
2388*9e564957SAndroid Build Coastguard Worker 	if (se->conn.proto_minor >= 13) {
2389*9e564957SAndroid Build Coastguard Worker 		if (se->conn.max_background >= (1 << 16))
2390*9e564957SAndroid Build Coastguard Worker 			se->conn.max_background = (1 << 16) - 1;
2391*9e564957SAndroid Build Coastguard Worker 		if (se->conn.congestion_threshold > se->conn.max_background)
2392*9e564957SAndroid Build Coastguard Worker 			se->conn.congestion_threshold = se->conn.max_background;
2393*9e564957SAndroid Build Coastguard Worker 		if (!se->conn.congestion_threshold) {
2394*9e564957SAndroid Build Coastguard Worker 			se->conn.congestion_threshold =
2395*9e564957SAndroid Build Coastguard Worker 				se->conn.max_background * 3 / 4;
2396*9e564957SAndroid Build Coastguard Worker 		}
2397*9e564957SAndroid Build Coastguard Worker 
2398*9e564957SAndroid Build Coastguard Worker 		outarg.max_background = se->conn.max_background;
2399*9e564957SAndroid Build Coastguard Worker 		outarg.congestion_threshold = se->conn.congestion_threshold;
2400*9e564957SAndroid Build Coastguard Worker 	}
2401*9e564957SAndroid Build Coastguard Worker 	if (se->conn.proto_minor >= 23)
2402*9e564957SAndroid Build Coastguard Worker 		outarg.time_gran = se->conn.time_gran;
2403*9e564957SAndroid Build Coastguard Worker 
2404*9e564957SAndroid Build Coastguard Worker 	if (se->debug) {
2405*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_DEBUG, "   INIT: %u.%u\n", outarg.major, outarg.minor);
2406*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_DEBUG, "   flags=0x%08x\n", outarg.flags);
2407*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_DEBUG, "   max_readahead=0x%08x\n",
2408*9e564957SAndroid Build Coastguard Worker 			outarg.max_readahead);
2409*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_DEBUG, "   max_write=0x%08x\n", outarg.max_write);
2410*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_DEBUG, "   max_background=%i\n",
2411*9e564957SAndroid Build Coastguard Worker 			outarg.max_background);
2412*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_DEBUG, "   congestion_threshold=%i\n",
2413*9e564957SAndroid Build Coastguard Worker 			outarg.congestion_threshold);
2414*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_DEBUG, "   time_gran=%u\n",
2415*9e564957SAndroid Build Coastguard Worker 			outarg.time_gran);
2416*9e564957SAndroid Build Coastguard Worker 		if (se->conn.want & FUSE_CAP_PASSTHROUGH)
2417*9e564957SAndroid Build Coastguard Worker 			fuse_log(FUSE_LOG_DEBUG, "   max_stack_depth=%u\n",
2418*9e564957SAndroid Build Coastguard Worker 				outarg.max_stack_depth);
2419*9e564957SAndroid Build Coastguard Worker 	}
2420*9e564957SAndroid Build Coastguard Worker 	if (arg->minor < 5)
2421*9e564957SAndroid Build Coastguard Worker 		outargsize = FUSE_COMPAT_INIT_OUT_SIZE;
2422*9e564957SAndroid Build Coastguard Worker 	else if (arg->minor < 23)
2423*9e564957SAndroid Build Coastguard Worker 		outargsize = FUSE_COMPAT_22_INIT_OUT_SIZE;
2424*9e564957SAndroid Build Coastguard Worker 
2425*9e564957SAndroid Build Coastguard Worker 	send_reply_ok(req, &outarg, outargsize);
2426*9e564957SAndroid Build Coastguard Worker }
2427*9e564957SAndroid Build Coastguard Worker 
2428*9e564957SAndroid Build Coastguard Worker static void do_destroy(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
2429*9e564957SAndroid Build Coastguard Worker {
2430*9e564957SAndroid Build Coastguard Worker 	struct fuse_session *se = req->se;
2431*9e564957SAndroid Build Coastguard Worker 
2432*9e564957SAndroid Build Coastguard Worker 	(void) nodeid;
2433*9e564957SAndroid Build Coastguard Worker 	(void) inarg;
2434*9e564957SAndroid Build Coastguard Worker 
2435*9e564957SAndroid Build Coastguard Worker 	se->got_destroy = 1;
2436*9e564957SAndroid Build Coastguard Worker 	se->got_init = 0;
2437*9e564957SAndroid Build Coastguard Worker 	if (se->op.destroy)
2438*9e564957SAndroid Build Coastguard Worker 		se->op.destroy(se->userdata);
2439*9e564957SAndroid Build Coastguard Worker 
2440*9e564957SAndroid Build Coastguard Worker 	send_reply_ok(req, NULL, 0);
2441*9e564957SAndroid Build Coastguard Worker }
2442*9e564957SAndroid Build Coastguard Worker 
2443*9e564957SAndroid Build Coastguard Worker static void list_del_nreq(struct fuse_notify_req *nreq)
2444*9e564957SAndroid Build Coastguard Worker {
2445*9e564957SAndroid Build Coastguard Worker 	struct fuse_notify_req *prev = nreq->prev;
2446*9e564957SAndroid Build Coastguard Worker 	struct fuse_notify_req *next = nreq->next;
2447*9e564957SAndroid Build Coastguard Worker 	prev->next = next;
2448*9e564957SAndroid Build Coastguard Worker 	next->prev = prev;
2449*9e564957SAndroid Build Coastguard Worker }
2450*9e564957SAndroid Build Coastguard Worker 
2451*9e564957SAndroid Build Coastguard Worker static void list_add_nreq(struct fuse_notify_req *nreq,
2452*9e564957SAndroid Build Coastguard Worker 			  struct fuse_notify_req *next)
2453*9e564957SAndroid Build Coastguard Worker {
2454*9e564957SAndroid Build Coastguard Worker 	struct fuse_notify_req *prev = next->prev;
2455*9e564957SAndroid Build Coastguard Worker 	nreq->next = next;
2456*9e564957SAndroid Build Coastguard Worker 	nreq->prev = prev;
2457*9e564957SAndroid Build Coastguard Worker 	prev->next = nreq;
2458*9e564957SAndroid Build Coastguard Worker 	next->prev = nreq;
2459*9e564957SAndroid Build Coastguard Worker }
2460*9e564957SAndroid Build Coastguard Worker 
2461*9e564957SAndroid Build Coastguard Worker static void list_init_nreq(struct fuse_notify_req *nreq)
2462*9e564957SAndroid Build Coastguard Worker {
2463*9e564957SAndroid Build Coastguard Worker 	nreq->next = nreq;
2464*9e564957SAndroid Build Coastguard Worker 	nreq->prev = nreq;
2465*9e564957SAndroid Build Coastguard Worker }
2466*9e564957SAndroid Build Coastguard Worker 
2467*9e564957SAndroid Build Coastguard Worker static void do_notify_reply(fuse_req_t req, fuse_ino_t nodeid,
2468*9e564957SAndroid Build Coastguard Worker 			    const void *inarg, const struct fuse_buf *buf)
2469*9e564957SAndroid Build Coastguard Worker {
2470*9e564957SAndroid Build Coastguard Worker 	struct fuse_session *se = req->se;
2471*9e564957SAndroid Build Coastguard Worker 	struct fuse_notify_req *nreq;
2472*9e564957SAndroid Build Coastguard Worker 	struct fuse_notify_req *head;
2473*9e564957SAndroid Build Coastguard Worker 
2474*9e564957SAndroid Build Coastguard Worker 	pthread_mutex_lock(&se->lock);
2475*9e564957SAndroid Build Coastguard Worker 	head = &se->notify_list;
2476*9e564957SAndroid Build Coastguard Worker 	for (nreq = head->next; nreq != head; nreq = nreq->next) {
2477*9e564957SAndroid Build Coastguard Worker 		if (nreq->unique == req->unique) {
2478*9e564957SAndroid Build Coastguard Worker 			list_del_nreq(nreq);
2479*9e564957SAndroid Build Coastguard Worker 			break;
2480*9e564957SAndroid Build Coastguard Worker 		}
2481*9e564957SAndroid Build Coastguard Worker 	}
2482*9e564957SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&se->lock);
2483*9e564957SAndroid Build Coastguard Worker 
2484*9e564957SAndroid Build Coastguard Worker 	if (nreq != head)
2485*9e564957SAndroid Build Coastguard Worker 		nreq->reply(nreq, req, nodeid, inarg, buf);
2486*9e564957SAndroid Build Coastguard Worker }
2487*9e564957SAndroid Build Coastguard Worker 
2488*9e564957SAndroid Build Coastguard Worker static int send_notify_iov(struct fuse_session *se, int notify_code,
2489*9e564957SAndroid Build Coastguard Worker 			   struct iovec *iov, int count)
2490*9e564957SAndroid Build Coastguard Worker {
2491*9e564957SAndroid Build Coastguard Worker 	struct fuse_out_header out;
2492*9e564957SAndroid Build Coastguard Worker 
2493*9e564957SAndroid Build Coastguard Worker 	if (!se->got_init)
2494*9e564957SAndroid Build Coastguard Worker 		return -ENOTCONN;
2495*9e564957SAndroid Build Coastguard Worker 
2496*9e564957SAndroid Build Coastguard Worker 	out.unique = 0;
2497*9e564957SAndroid Build Coastguard Worker 	out.error = notify_code;
2498*9e564957SAndroid Build Coastguard Worker 	iov[0].iov_base = &out;
2499*9e564957SAndroid Build Coastguard Worker 	iov[0].iov_len = sizeof(struct fuse_out_header);
2500*9e564957SAndroid Build Coastguard Worker 
2501*9e564957SAndroid Build Coastguard Worker 	return fuse_send_msg(se, NULL, iov, count);
2502*9e564957SAndroid Build Coastguard Worker }
2503*9e564957SAndroid Build Coastguard Worker 
2504*9e564957SAndroid Build Coastguard Worker int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph)
2505*9e564957SAndroid Build Coastguard Worker {
2506*9e564957SAndroid Build Coastguard Worker 	if (ph != NULL) {
2507*9e564957SAndroid Build Coastguard Worker 		struct fuse_notify_poll_wakeup_out outarg;
2508*9e564957SAndroid Build Coastguard Worker 		struct iovec iov[2];
2509*9e564957SAndroid Build Coastguard Worker 
2510*9e564957SAndroid Build Coastguard Worker 		outarg.kh = ph->kh;
2511*9e564957SAndroid Build Coastguard Worker 
2512*9e564957SAndroid Build Coastguard Worker 		iov[1].iov_base = &outarg;
2513*9e564957SAndroid Build Coastguard Worker 		iov[1].iov_len = sizeof(outarg);
2514*9e564957SAndroid Build Coastguard Worker 
2515*9e564957SAndroid Build Coastguard Worker 		return send_notify_iov(ph->se, FUSE_NOTIFY_POLL, iov, 2);
2516*9e564957SAndroid Build Coastguard Worker 	} else {
2517*9e564957SAndroid Build Coastguard Worker 		return 0;
2518*9e564957SAndroid Build Coastguard Worker 	}
2519*9e564957SAndroid Build Coastguard Worker }
2520*9e564957SAndroid Build Coastguard Worker 
2521*9e564957SAndroid Build Coastguard Worker int fuse_lowlevel_notify_inval_inode(struct fuse_session *se, fuse_ino_t ino,
2522*9e564957SAndroid Build Coastguard Worker 				     off_t off, off_t len)
2523*9e564957SAndroid Build Coastguard Worker {
2524*9e564957SAndroid Build Coastguard Worker 	struct fuse_notify_inval_inode_out outarg;
2525*9e564957SAndroid Build Coastguard Worker 	struct iovec iov[2];
2526*9e564957SAndroid Build Coastguard Worker 
2527*9e564957SAndroid Build Coastguard Worker 	if (!se)
2528*9e564957SAndroid Build Coastguard Worker 		return -EINVAL;
2529*9e564957SAndroid Build Coastguard Worker 
2530*9e564957SAndroid Build Coastguard Worker 	if (se->conn.proto_minor < 12)
2531*9e564957SAndroid Build Coastguard Worker 		return -ENOSYS;
2532*9e564957SAndroid Build Coastguard Worker 
2533*9e564957SAndroid Build Coastguard Worker 	outarg.ino = ino;
2534*9e564957SAndroid Build Coastguard Worker 	outarg.off = off;
2535*9e564957SAndroid Build Coastguard Worker 	outarg.len = len;
2536*9e564957SAndroid Build Coastguard Worker 
2537*9e564957SAndroid Build Coastguard Worker 	iov[1].iov_base = &outarg;
2538*9e564957SAndroid Build Coastguard Worker 	iov[1].iov_len = sizeof(outarg);
2539*9e564957SAndroid Build Coastguard Worker 
2540*9e564957SAndroid Build Coastguard Worker 	return send_notify_iov(se, FUSE_NOTIFY_INVAL_INODE, iov, 2);
2541*9e564957SAndroid Build Coastguard Worker }
2542*9e564957SAndroid Build Coastguard Worker 
2543*9e564957SAndroid Build Coastguard Worker /**
2544*9e564957SAndroid Build Coastguard Worker  * Notify parent attributes and the dentry matching parent/name
2545*9e564957SAndroid Build Coastguard Worker  *
2546*9e564957SAndroid Build Coastguard Worker  * Underlying base function for fuse_lowlevel_notify_inval_entry() and
2547*9e564957SAndroid Build Coastguard Worker  * fuse_lowlevel_notify_expire_entry().
2548*9e564957SAndroid Build Coastguard Worker  *
2549*9e564957SAndroid Build Coastguard Worker  * @warning
2550*9e564957SAndroid Build Coastguard Worker  * Only checks if fuse_lowlevel_notify_inval_entry() is supported by
2551*9e564957SAndroid Build Coastguard Worker  * the kernel. All other flags will fall back to
2552*9e564957SAndroid Build Coastguard Worker  * fuse_lowlevel_notify_inval_entry() if not supported!
2553*9e564957SAndroid Build Coastguard Worker  * DO THE PROPER CHECKS IN THE DERIVED FUNCTION!
2554*9e564957SAndroid Build Coastguard Worker  *
2555*9e564957SAndroid Build Coastguard Worker  * @param se the session object
2556*9e564957SAndroid Build Coastguard Worker  * @param parent inode number
2557*9e564957SAndroid Build Coastguard Worker  * @param name file name
2558*9e564957SAndroid Build Coastguard Worker  * @param namelen strlen() of file name
2559*9e564957SAndroid Build Coastguard Worker  * @param flags flags to control if the entry should be expired or invalidated
2560*9e564957SAndroid Build Coastguard Worker  * @return zero for success, -errno for failure
2561*9e564957SAndroid Build Coastguard Worker */
2562*9e564957SAndroid Build Coastguard Worker static int fuse_lowlevel_notify_entry(struct fuse_session *se, fuse_ino_t parent,
2563*9e564957SAndroid Build Coastguard Worker 							const char *name, size_t namelen,
2564*9e564957SAndroid Build Coastguard Worker 							enum fuse_notify_entry_flags flags)
2565*9e564957SAndroid Build Coastguard Worker {
2566*9e564957SAndroid Build Coastguard Worker 	struct fuse_notify_inval_entry_out outarg;
2567*9e564957SAndroid Build Coastguard Worker 	struct iovec iov[3];
2568*9e564957SAndroid Build Coastguard Worker 
2569*9e564957SAndroid Build Coastguard Worker 	if (!se)
2570*9e564957SAndroid Build Coastguard Worker 		return -EINVAL;
2571*9e564957SAndroid Build Coastguard Worker 
2572*9e564957SAndroid Build Coastguard Worker 	if (se->conn.proto_minor < 12)
2573*9e564957SAndroid Build Coastguard Worker 		return -ENOSYS;
2574*9e564957SAndroid Build Coastguard Worker 
2575*9e564957SAndroid Build Coastguard Worker 	outarg.parent = parent;
2576*9e564957SAndroid Build Coastguard Worker 	outarg.namelen = namelen;
2577*9e564957SAndroid Build Coastguard Worker 	outarg.flags = 0;
2578*9e564957SAndroid Build Coastguard Worker 	if (flags & FUSE_LL_EXPIRE_ONLY)
2579*9e564957SAndroid Build Coastguard Worker 		outarg.flags |= FUSE_EXPIRE_ONLY;
2580*9e564957SAndroid Build Coastguard Worker 
2581*9e564957SAndroid Build Coastguard Worker 	iov[1].iov_base = &outarg;
2582*9e564957SAndroid Build Coastguard Worker 	iov[1].iov_len = sizeof(outarg);
2583*9e564957SAndroid Build Coastguard Worker 	iov[2].iov_base = (void *)name;
2584*9e564957SAndroid Build Coastguard Worker 	iov[2].iov_len = namelen + 1;
2585*9e564957SAndroid Build Coastguard Worker 
2586*9e564957SAndroid Build Coastguard Worker 	return send_notify_iov(se, FUSE_NOTIFY_INVAL_ENTRY, iov, 3);
2587*9e564957SAndroid Build Coastguard Worker }
2588*9e564957SAndroid Build Coastguard Worker 
2589*9e564957SAndroid Build Coastguard Worker int fuse_lowlevel_notify_inval_entry(struct fuse_session *se, fuse_ino_t parent,
2590*9e564957SAndroid Build Coastguard Worker 						 const char *name, size_t namelen)
2591*9e564957SAndroid Build Coastguard Worker {
2592*9e564957SAndroid Build Coastguard Worker 	return fuse_lowlevel_notify_entry(se, parent, name, namelen, FUSE_LL_INVALIDATE);
2593*9e564957SAndroid Build Coastguard Worker }
2594*9e564957SAndroid Build Coastguard Worker 
2595*9e564957SAndroid Build Coastguard Worker int fuse_lowlevel_notify_expire_entry(struct fuse_session *se, fuse_ino_t parent,
2596*9e564957SAndroid Build Coastguard Worker 							const char *name, size_t namelen)
2597*9e564957SAndroid Build Coastguard Worker {
2598*9e564957SAndroid Build Coastguard Worker 	if (!se)
2599*9e564957SAndroid Build Coastguard Worker 		return -EINVAL;
2600*9e564957SAndroid Build Coastguard Worker 
2601*9e564957SAndroid Build Coastguard Worker 	if (!(se->conn.capable & FUSE_CAP_EXPIRE_ONLY))
2602*9e564957SAndroid Build Coastguard Worker 		return -ENOSYS;
2603*9e564957SAndroid Build Coastguard Worker 
2604*9e564957SAndroid Build Coastguard Worker 	return fuse_lowlevel_notify_entry(se, parent, name, namelen, FUSE_LL_EXPIRE_ONLY);
2605*9e564957SAndroid Build Coastguard Worker }
2606*9e564957SAndroid Build Coastguard Worker 
2607*9e564957SAndroid Build Coastguard Worker 
2608*9e564957SAndroid Build Coastguard Worker int fuse_lowlevel_notify_delete(struct fuse_session *se,
2609*9e564957SAndroid Build Coastguard Worker 				fuse_ino_t parent, fuse_ino_t child,
2610*9e564957SAndroid Build Coastguard Worker 				const char *name, size_t namelen)
2611*9e564957SAndroid Build Coastguard Worker {
2612*9e564957SAndroid Build Coastguard Worker 	struct fuse_notify_delete_out outarg;
2613*9e564957SAndroid Build Coastguard Worker 	struct iovec iov[3];
2614*9e564957SAndroid Build Coastguard Worker 
2615*9e564957SAndroid Build Coastguard Worker 	if (!se)
2616*9e564957SAndroid Build Coastguard Worker 		return -EINVAL;
2617*9e564957SAndroid Build Coastguard Worker 
2618*9e564957SAndroid Build Coastguard Worker 	if (se->conn.proto_minor < 18)
2619*9e564957SAndroid Build Coastguard Worker 		return -ENOSYS;
2620*9e564957SAndroid Build Coastguard Worker 
2621*9e564957SAndroid Build Coastguard Worker 	outarg.parent = parent;
2622*9e564957SAndroid Build Coastguard Worker 	outarg.child = child;
2623*9e564957SAndroid Build Coastguard Worker 	outarg.namelen = namelen;
2624*9e564957SAndroid Build Coastguard Worker 	outarg.padding = 0;
2625*9e564957SAndroid Build Coastguard Worker 
2626*9e564957SAndroid Build Coastguard Worker 	iov[1].iov_base = &outarg;
2627*9e564957SAndroid Build Coastguard Worker 	iov[1].iov_len = sizeof(outarg);
2628*9e564957SAndroid Build Coastguard Worker 	iov[2].iov_base = (void *)name;
2629*9e564957SAndroid Build Coastguard Worker 	iov[2].iov_len = namelen + 1;
2630*9e564957SAndroid Build Coastguard Worker 
2631*9e564957SAndroid Build Coastguard Worker 	return send_notify_iov(se, FUSE_NOTIFY_DELETE, iov, 3);
2632*9e564957SAndroid Build Coastguard Worker }
2633*9e564957SAndroid Build Coastguard Worker 
2634*9e564957SAndroid Build Coastguard Worker int fuse_lowlevel_notify_store(struct fuse_session *se, fuse_ino_t ino,
2635*9e564957SAndroid Build Coastguard Worker 			       off_t offset, struct fuse_bufvec *bufv,
2636*9e564957SAndroid Build Coastguard Worker 			       enum fuse_buf_copy_flags flags)
2637*9e564957SAndroid Build Coastguard Worker {
2638*9e564957SAndroid Build Coastguard Worker 	struct fuse_out_header out;
2639*9e564957SAndroid Build Coastguard Worker 	struct fuse_notify_store_out outarg;
2640*9e564957SAndroid Build Coastguard Worker 	struct iovec iov[3];
2641*9e564957SAndroid Build Coastguard Worker 	size_t size = fuse_buf_size(bufv);
2642*9e564957SAndroid Build Coastguard Worker 	int res;
2643*9e564957SAndroid Build Coastguard Worker 
2644*9e564957SAndroid Build Coastguard Worker 	if (!se)
2645*9e564957SAndroid Build Coastguard Worker 		return -EINVAL;
2646*9e564957SAndroid Build Coastguard Worker 
2647*9e564957SAndroid Build Coastguard Worker 	if (se->conn.proto_minor < 15)
2648*9e564957SAndroid Build Coastguard Worker 		return -ENOSYS;
2649*9e564957SAndroid Build Coastguard Worker 
2650*9e564957SAndroid Build Coastguard Worker 	out.unique = 0;
2651*9e564957SAndroid Build Coastguard Worker 	out.error = FUSE_NOTIFY_STORE;
2652*9e564957SAndroid Build Coastguard Worker 
2653*9e564957SAndroid Build Coastguard Worker 	outarg.nodeid = ino;
2654*9e564957SAndroid Build Coastguard Worker 	outarg.offset = offset;
2655*9e564957SAndroid Build Coastguard Worker 	outarg.size = size;
2656*9e564957SAndroid Build Coastguard Worker 	outarg.padding = 0;
2657*9e564957SAndroid Build Coastguard Worker 
2658*9e564957SAndroid Build Coastguard Worker 	iov[0].iov_base = &out;
2659*9e564957SAndroid Build Coastguard Worker 	iov[0].iov_len = sizeof(out);
2660*9e564957SAndroid Build Coastguard Worker 	iov[1].iov_base = &outarg;
2661*9e564957SAndroid Build Coastguard Worker 	iov[1].iov_len = sizeof(outarg);
2662*9e564957SAndroid Build Coastguard Worker 
2663*9e564957SAndroid Build Coastguard Worker 	res = fuse_send_data_iov(se, NULL, iov, 2, bufv, flags);
2664*9e564957SAndroid Build Coastguard Worker 	if (res > 0)
2665*9e564957SAndroid Build Coastguard Worker 		res = -res;
2666*9e564957SAndroid Build Coastguard Worker 
2667*9e564957SAndroid Build Coastguard Worker 	return res;
2668*9e564957SAndroid Build Coastguard Worker }
2669*9e564957SAndroid Build Coastguard Worker 
2670*9e564957SAndroid Build Coastguard Worker struct fuse_retrieve_req {
2671*9e564957SAndroid Build Coastguard Worker 	struct fuse_notify_req nreq;
2672*9e564957SAndroid Build Coastguard Worker 	void *cookie;
2673*9e564957SAndroid Build Coastguard Worker };
2674*9e564957SAndroid Build Coastguard Worker 
2675*9e564957SAndroid Build Coastguard Worker static void fuse_ll_retrieve_reply(struct fuse_notify_req *nreq,
2676*9e564957SAndroid Build Coastguard Worker 				   fuse_req_t req, fuse_ino_t ino,
2677*9e564957SAndroid Build Coastguard Worker 				   const void *inarg,
2678*9e564957SAndroid Build Coastguard Worker 				   const struct fuse_buf *ibuf)
2679*9e564957SAndroid Build Coastguard Worker {
2680*9e564957SAndroid Build Coastguard Worker 	struct fuse_session *se = req->se;
2681*9e564957SAndroid Build Coastguard Worker 	struct fuse_retrieve_req *rreq =
2682*9e564957SAndroid Build Coastguard Worker 		container_of(nreq, struct fuse_retrieve_req, nreq);
2683*9e564957SAndroid Build Coastguard Worker 	const struct fuse_notify_retrieve_in *arg = inarg;
2684*9e564957SAndroid Build Coastguard Worker 	struct fuse_bufvec bufv = {
2685*9e564957SAndroid Build Coastguard Worker 		.buf[0] = *ibuf,
2686*9e564957SAndroid Build Coastguard Worker 		.count = 1,
2687*9e564957SAndroid Build Coastguard Worker 	};
2688*9e564957SAndroid Build Coastguard Worker 
2689*9e564957SAndroid Build Coastguard Worker 	if (!(bufv.buf[0].flags & FUSE_BUF_IS_FD))
2690*9e564957SAndroid Build Coastguard Worker 		bufv.buf[0].mem = PARAM(arg);
2691*9e564957SAndroid Build Coastguard Worker 
2692*9e564957SAndroid Build Coastguard Worker 	bufv.buf[0].size -= sizeof(struct fuse_in_header) +
2693*9e564957SAndroid Build Coastguard Worker 		sizeof(struct fuse_notify_retrieve_in);
2694*9e564957SAndroid Build Coastguard Worker 
2695*9e564957SAndroid Build Coastguard Worker 	if (bufv.buf[0].size < arg->size) {
2696*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: retrieve reply: buffer size too small\n");
2697*9e564957SAndroid Build Coastguard Worker 		fuse_reply_none(req);
2698*9e564957SAndroid Build Coastguard Worker 		goto out;
2699*9e564957SAndroid Build Coastguard Worker 	}
2700*9e564957SAndroid Build Coastguard Worker 	bufv.buf[0].size = arg->size;
2701*9e564957SAndroid Build Coastguard Worker 
2702*9e564957SAndroid Build Coastguard Worker 	if (se->op.retrieve_reply) {
2703*9e564957SAndroid Build Coastguard Worker 		se->op.retrieve_reply(req, rreq->cookie, ino,
2704*9e564957SAndroid Build Coastguard Worker 					  arg->offset, &bufv);
2705*9e564957SAndroid Build Coastguard Worker 	} else {
2706*9e564957SAndroid Build Coastguard Worker 		fuse_reply_none(req);
2707*9e564957SAndroid Build Coastguard Worker 	}
2708*9e564957SAndroid Build Coastguard Worker out:
2709*9e564957SAndroid Build Coastguard Worker 	free(rreq);
2710*9e564957SAndroid Build Coastguard Worker 	if ((ibuf->flags & FUSE_BUF_IS_FD) && bufv.idx < bufv.count)
2711*9e564957SAndroid Build Coastguard Worker 		fuse_ll_clear_pipe(se);
2712*9e564957SAndroid Build Coastguard Worker }
2713*9e564957SAndroid Build Coastguard Worker 
2714*9e564957SAndroid Build Coastguard Worker int fuse_lowlevel_notify_retrieve(struct fuse_session *se, fuse_ino_t ino,
2715*9e564957SAndroid Build Coastguard Worker 				  size_t size, off_t offset, void *cookie)
2716*9e564957SAndroid Build Coastguard Worker {
2717*9e564957SAndroid Build Coastguard Worker 	struct fuse_notify_retrieve_out outarg;
2718*9e564957SAndroid Build Coastguard Worker 	struct iovec iov[2];
2719*9e564957SAndroid Build Coastguard Worker 	struct fuse_retrieve_req *rreq;
2720*9e564957SAndroid Build Coastguard Worker 	int err;
2721*9e564957SAndroid Build Coastguard Worker 
2722*9e564957SAndroid Build Coastguard Worker 	if (!se)
2723*9e564957SAndroid Build Coastguard Worker 		return -EINVAL;
2724*9e564957SAndroid Build Coastguard Worker 
2725*9e564957SAndroid Build Coastguard Worker 	if (se->conn.proto_minor < 15)
2726*9e564957SAndroid Build Coastguard Worker 		return -ENOSYS;
2727*9e564957SAndroid Build Coastguard Worker 
2728*9e564957SAndroid Build Coastguard Worker 	rreq = malloc(sizeof(*rreq));
2729*9e564957SAndroid Build Coastguard Worker 	if (rreq == NULL)
2730*9e564957SAndroid Build Coastguard Worker 		return -ENOMEM;
2731*9e564957SAndroid Build Coastguard Worker 
2732*9e564957SAndroid Build Coastguard Worker 	pthread_mutex_lock(&se->lock);
2733*9e564957SAndroid Build Coastguard Worker 	rreq->cookie = cookie;
2734*9e564957SAndroid Build Coastguard Worker 	rreq->nreq.unique = se->notify_ctr++;
2735*9e564957SAndroid Build Coastguard Worker 	rreq->nreq.reply = fuse_ll_retrieve_reply;
2736*9e564957SAndroid Build Coastguard Worker 	list_add_nreq(&rreq->nreq, &se->notify_list);
2737*9e564957SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&se->lock);
2738*9e564957SAndroid Build Coastguard Worker 
2739*9e564957SAndroid Build Coastguard Worker 	outarg.notify_unique = rreq->nreq.unique;
2740*9e564957SAndroid Build Coastguard Worker 	outarg.nodeid = ino;
2741*9e564957SAndroid Build Coastguard Worker 	outarg.offset = offset;
2742*9e564957SAndroid Build Coastguard Worker 	outarg.size = size;
2743*9e564957SAndroid Build Coastguard Worker 	outarg.padding = 0;
2744*9e564957SAndroid Build Coastguard Worker 
2745*9e564957SAndroid Build Coastguard Worker 	iov[1].iov_base = &outarg;
2746*9e564957SAndroid Build Coastguard Worker 	iov[1].iov_len = sizeof(outarg);
2747*9e564957SAndroid Build Coastguard Worker 
2748*9e564957SAndroid Build Coastguard Worker 	err = send_notify_iov(se, FUSE_NOTIFY_RETRIEVE, iov, 2);
2749*9e564957SAndroid Build Coastguard Worker 	if (err) {
2750*9e564957SAndroid Build Coastguard Worker 		pthread_mutex_lock(&se->lock);
2751*9e564957SAndroid Build Coastguard Worker 		list_del_nreq(&rreq->nreq);
2752*9e564957SAndroid Build Coastguard Worker 		pthread_mutex_unlock(&se->lock);
2753*9e564957SAndroid Build Coastguard Worker 		free(rreq);
2754*9e564957SAndroid Build Coastguard Worker 	}
2755*9e564957SAndroid Build Coastguard Worker 
2756*9e564957SAndroid Build Coastguard Worker 	return err;
2757*9e564957SAndroid Build Coastguard Worker }
2758*9e564957SAndroid Build Coastguard Worker 
2759*9e564957SAndroid Build Coastguard Worker void *fuse_req_userdata(fuse_req_t req)
2760*9e564957SAndroid Build Coastguard Worker {
2761*9e564957SAndroid Build Coastguard Worker 	return req->se->userdata;
2762*9e564957SAndroid Build Coastguard Worker }
2763*9e564957SAndroid Build Coastguard Worker 
2764*9e564957SAndroid Build Coastguard Worker const struct fuse_ctx *fuse_req_ctx(fuse_req_t req)
2765*9e564957SAndroid Build Coastguard Worker {
2766*9e564957SAndroid Build Coastguard Worker 	return &req->ctx;
2767*9e564957SAndroid Build Coastguard Worker }
2768*9e564957SAndroid Build Coastguard Worker 
2769*9e564957SAndroid Build Coastguard Worker void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func,
2770*9e564957SAndroid Build Coastguard Worker 			     void *data)
2771*9e564957SAndroid Build Coastguard Worker {
2772*9e564957SAndroid Build Coastguard Worker 	pthread_mutex_lock(&req->lock);
2773*9e564957SAndroid Build Coastguard Worker 	pthread_mutex_lock(&req->se->lock);
2774*9e564957SAndroid Build Coastguard Worker 	req->u.ni.func = func;
2775*9e564957SAndroid Build Coastguard Worker 	req->u.ni.data = data;
2776*9e564957SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&req->se->lock);
2777*9e564957SAndroid Build Coastguard Worker 	if (req->interrupted && func)
2778*9e564957SAndroid Build Coastguard Worker 		func(req, data);
2779*9e564957SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&req->lock);
2780*9e564957SAndroid Build Coastguard Worker }
2781*9e564957SAndroid Build Coastguard Worker 
2782*9e564957SAndroid Build Coastguard Worker int fuse_req_interrupted(fuse_req_t req)
2783*9e564957SAndroid Build Coastguard Worker {
2784*9e564957SAndroid Build Coastguard Worker 	int interrupted;
2785*9e564957SAndroid Build Coastguard Worker 
2786*9e564957SAndroid Build Coastguard Worker 	pthread_mutex_lock(&req->se->lock);
2787*9e564957SAndroid Build Coastguard Worker 	interrupted = req->interrupted;
2788*9e564957SAndroid Build Coastguard Worker 	pthread_mutex_unlock(&req->se->lock);
2789*9e564957SAndroid Build Coastguard Worker 
2790*9e564957SAndroid Build Coastguard Worker 	return interrupted;
2791*9e564957SAndroid Build Coastguard Worker }
2792*9e564957SAndroid Build Coastguard Worker 
2793*9e564957SAndroid Build Coastguard Worker static struct {
2794*9e564957SAndroid Build Coastguard Worker 	void (*func)(fuse_req_t, fuse_ino_t, const void *);
2795*9e564957SAndroid Build Coastguard Worker 	const char *name;
2796*9e564957SAndroid Build Coastguard Worker } fuse_ll_ops[] = {
2797*9e564957SAndroid Build Coastguard Worker 	[FUSE_LOOKUP]	   = { do_lookup,      "LOOKUP"	     },
2798*9e564957SAndroid Build Coastguard Worker 	[FUSE_FORGET]	   = { do_forget,      "FORGET"	     },
2799*9e564957SAndroid Build Coastguard Worker 	[FUSE_GETATTR]	   = { do_getattr,     "GETATTR"     },
2800*9e564957SAndroid Build Coastguard Worker 	[FUSE_SETATTR]	   = { do_setattr,     "SETATTR"     },
2801*9e564957SAndroid Build Coastguard Worker 	[FUSE_READLINK]	   = { do_readlink,    "READLINK"    },
2802*9e564957SAndroid Build Coastguard Worker 	[FUSE_CANONICAL_PATH] = { do_canonical_path, "CANONICAL_PATH" },
2803*9e564957SAndroid Build Coastguard Worker 	[FUSE_SYMLINK]	   = { do_symlink,     "SYMLINK"     },
2804*9e564957SAndroid Build Coastguard Worker 	[FUSE_MKNOD]	   = { do_mknod,       "MKNOD"	     },
2805*9e564957SAndroid Build Coastguard Worker 	[FUSE_MKDIR]	   = { do_mkdir,       "MKDIR"	     },
2806*9e564957SAndroid Build Coastguard Worker 	[FUSE_UNLINK]	   = { do_unlink,      "UNLINK"	     },
2807*9e564957SAndroid Build Coastguard Worker 	[FUSE_RMDIR]	   = { do_rmdir,       "RMDIR"	     },
2808*9e564957SAndroid Build Coastguard Worker 	[FUSE_RENAME]	   = { do_rename,      "RENAME"	     },
2809*9e564957SAndroid Build Coastguard Worker 	[FUSE_LINK]	   = { do_link,	       "LINK"	     },
2810*9e564957SAndroid Build Coastguard Worker 	[FUSE_OPEN]	   = { do_open,	       "OPEN"	     },
2811*9e564957SAndroid Build Coastguard Worker 	[FUSE_READ]	   = { do_read,	       "READ"	     },
2812*9e564957SAndroid Build Coastguard Worker 	[FUSE_WRITE]	   = { do_write,       "WRITE"	     },
2813*9e564957SAndroid Build Coastguard Worker 	[FUSE_STATFS]	   = { do_statfs,      "STATFS"	     },
2814*9e564957SAndroid Build Coastguard Worker 	[FUSE_RELEASE]	   = { do_release,     "RELEASE"     },
2815*9e564957SAndroid Build Coastguard Worker 	[FUSE_FSYNC]	   = { do_fsync,       "FSYNC"	     },
2816*9e564957SAndroid Build Coastguard Worker 	[FUSE_SETXATTR]	   = { do_setxattr,    "SETXATTR"    },
2817*9e564957SAndroid Build Coastguard Worker 	[FUSE_GETXATTR]	   = { do_getxattr,    "GETXATTR"    },
2818*9e564957SAndroid Build Coastguard Worker 	[FUSE_LISTXATTR]   = { do_listxattr,   "LISTXATTR"   },
2819*9e564957SAndroid Build Coastguard Worker 	[FUSE_REMOVEXATTR] = { do_removexattr, "REMOVEXATTR" },
2820*9e564957SAndroid Build Coastguard Worker 	[FUSE_FLUSH]	   = { do_flush,       "FLUSH"	     },
2821*9e564957SAndroid Build Coastguard Worker 	[FUSE_INIT]	   = { do_init,	       "INIT"	     },
2822*9e564957SAndroid Build Coastguard Worker 	[FUSE_OPENDIR]	   = { do_opendir,     "OPENDIR"     },
2823*9e564957SAndroid Build Coastguard Worker 	[FUSE_READDIR]	   = { do_readdir,     "READDIR"     },
2824*9e564957SAndroid Build Coastguard Worker 	[FUSE_RELEASEDIR]  = { do_releasedir,  "RELEASEDIR"  },
2825*9e564957SAndroid Build Coastguard Worker 	[FUSE_FSYNCDIR]	   = { do_fsyncdir,    "FSYNCDIR"    },
2826*9e564957SAndroid Build Coastguard Worker 	[FUSE_GETLK]	   = { do_getlk,       "GETLK"	     },
2827*9e564957SAndroid Build Coastguard Worker 	[FUSE_SETLK]	   = { do_setlk,       "SETLK"	     },
2828*9e564957SAndroid Build Coastguard Worker 	[FUSE_SETLKW]	   = { do_setlkw,      "SETLKW"	     },
2829*9e564957SAndroid Build Coastguard Worker 	[FUSE_ACCESS]	   = { do_access,      "ACCESS"	     },
2830*9e564957SAndroid Build Coastguard Worker 	[FUSE_CREATE]	   = { do_create,      "CREATE"	     },
2831*9e564957SAndroid Build Coastguard Worker 	[FUSE_INTERRUPT]   = { do_interrupt,   "INTERRUPT"   },
2832*9e564957SAndroid Build Coastguard Worker 	[FUSE_BMAP]	   = { do_bmap,	       "BMAP"	     },
2833*9e564957SAndroid Build Coastguard Worker 	[FUSE_IOCTL]	   = { do_ioctl,       "IOCTL"	     },
2834*9e564957SAndroid Build Coastguard Worker 	[FUSE_POLL]	   = { do_poll,        "POLL"	     },
2835*9e564957SAndroid Build Coastguard Worker 	[FUSE_FALLOCATE]   = { do_fallocate,   "FALLOCATE"   },
2836*9e564957SAndroid Build Coastguard Worker 	[FUSE_DESTROY]	   = { do_destroy,     "DESTROY"     },
2837*9e564957SAndroid Build Coastguard Worker 	[FUSE_NOTIFY_REPLY] = { (void *) 1,    "NOTIFY_REPLY" },
2838*9e564957SAndroid Build Coastguard Worker 	[FUSE_BATCH_FORGET] = { do_batch_forget, "BATCH_FORGET" },
2839*9e564957SAndroid Build Coastguard Worker 	[FUSE_READDIRPLUS] = { do_readdirplus,	"READDIRPLUS"},
2840*9e564957SAndroid Build Coastguard Worker 	[FUSE_RENAME2]     = { do_rename2,      "RENAME2"    },
2841*9e564957SAndroid Build Coastguard Worker 	[FUSE_COPY_FILE_RANGE] = { do_copy_file_range, "COPY_FILE_RANGE" },
2842*9e564957SAndroid Build Coastguard Worker 	[FUSE_LSEEK]	   = { do_lseek,       "LSEEK"	     },
2843*9e564957SAndroid Build Coastguard Worker 	[CUSE_INIT]	   = { cuse_lowlevel_init, "CUSE_INIT"   },
2844*9e564957SAndroid Build Coastguard Worker };
2845*9e564957SAndroid Build Coastguard Worker 
2846*9e564957SAndroid Build Coastguard Worker static struct {
2847*9e564957SAndroid Build Coastguard Worker 	void (*func)( fuse_req_t, fuse_ino_t, const void *);
2848*9e564957SAndroid Build Coastguard Worker 	const char *name;
2849*9e564957SAndroid Build Coastguard Worker } fuse_ll_prefilter_ops[] = {};
2850*9e564957SAndroid Build Coastguard Worker 
2851*9e564957SAndroid Build Coastguard Worker static struct {
2852*9e564957SAndroid Build Coastguard Worker 	void (*func)( fuse_req_t, fuse_ino_t, uint32_t, const void *, size_t size);
2853*9e564957SAndroid Build Coastguard Worker } fuse_ll_postfilter_ops[] = {
2854*9e564957SAndroid Build Coastguard Worker 		[FUSE_LOOKUP] = {do_lookup_postfilter},
2855*9e564957SAndroid Build Coastguard Worker 		[FUSE_READDIR] = {do_readdir_postfilter},
2856*9e564957SAndroid Build Coastguard Worker };
2857*9e564957SAndroid Build Coastguard Worker 
2858*9e564957SAndroid Build Coastguard Worker #define FUSE_MAXOP (sizeof(fuse_ll_ops) / sizeof(fuse_ll_ops[0]))
2859*9e564957SAndroid Build Coastguard Worker 
2860*9e564957SAndroid Build Coastguard Worker static const char *opname(enum fuse_opcode opcode)
2861*9e564957SAndroid Build Coastguard Worker {
2862*9e564957SAndroid Build Coastguard Worker 	if (opcode >= FUSE_MAXOP || !fuse_ll_ops[opcode].name)
2863*9e564957SAndroid Build Coastguard Worker 		return "???";
2864*9e564957SAndroid Build Coastguard Worker 	else
2865*9e564957SAndroid Build Coastguard Worker 		return fuse_ll_ops[opcode].name;
2866*9e564957SAndroid Build Coastguard Worker }
2867*9e564957SAndroid Build Coastguard Worker 
2868*9e564957SAndroid Build Coastguard Worker static const char *opfiltername(int filter)
2869*9e564957SAndroid Build Coastguard Worker {
2870*9e564957SAndroid Build Coastguard Worker 	switch (filter) {
2871*9e564957SAndroid Build Coastguard Worker 	case 0:
2872*9e564957SAndroid Build Coastguard Worker 		return "NONE";
2873*9e564957SAndroid Build Coastguard Worker 	case FUSE_PREFILTER:
2874*9e564957SAndroid Build Coastguard Worker 		return "FUSE_PREFILTER";
2875*9e564957SAndroid Build Coastguard Worker 	case FUSE_POSTFILTER:
2876*9e564957SAndroid Build Coastguard Worker 		return "FUSE_POSTFILTER";
2877*9e564957SAndroid Build Coastguard Worker 	case FUSE_PREFILTER | FUSE_POSTFILTER:
2878*9e564957SAndroid Build Coastguard Worker 		return "FUSE_PREFILTER | FUSE_POSTFILTER";
2879*9e564957SAndroid Build Coastguard Worker 	default:
2880*9e564957SAndroid Build Coastguard Worker 		return "???";
2881*9e564957SAndroid Build Coastguard Worker 	}
2882*9e564957SAndroid Build Coastguard Worker }
2883*9e564957SAndroid Build Coastguard Worker 
2884*9e564957SAndroid Build Coastguard Worker static int fuse_ll_copy_from_pipe(struct fuse_bufvec *dst,
2885*9e564957SAndroid Build Coastguard Worker 				  struct fuse_bufvec *src)
2886*9e564957SAndroid Build Coastguard Worker {
2887*9e564957SAndroid Build Coastguard Worker 	ssize_t res = fuse_buf_copy(dst, src, 0);
2888*9e564957SAndroid Build Coastguard Worker 	if (res < 0) {
2889*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: copy from pipe: %s\n", strerror(-res));
2890*9e564957SAndroid Build Coastguard Worker 		return res;
2891*9e564957SAndroid Build Coastguard Worker 	}
2892*9e564957SAndroid Build Coastguard Worker 	if ((size_t)res < fuse_buf_size(dst)) {
2893*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: copy from pipe: short read\n");
2894*9e564957SAndroid Build Coastguard Worker 		return -1;
2895*9e564957SAndroid Build Coastguard Worker 	}
2896*9e564957SAndroid Build Coastguard Worker 	return 0;
2897*9e564957SAndroid Build Coastguard Worker }
2898*9e564957SAndroid Build Coastguard Worker 
2899*9e564957SAndroid Build Coastguard Worker void fuse_session_process_buf(struct fuse_session *se,
2900*9e564957SAndroid Build Coastguard Worker 			      const struct fuse_buf *buf)
2901*9e564957SAndroid Build Coastguard Worker {
2902*9e564957SAndroid Build Coastguard Worker 	fuse_session_process_buf_int(se, buf, NULL);
2903*9e564957SAndroid Build Coastguard Worker }
2904*9e564957SAndroid Build Coastguard Worker 
2905*9e564957SAndroid Build Coastguard Worker void fuse_session_process_buf_int(struct fuse_session *se,
2906*9e564957SAndroid Build Coastguard Worker 				  const struct fuse_buf *buf, struct fuse_chan *ch)
2907*9e564957SAndroid Build Coastguard Worker {
2908*9e564957SAndroid Build Coastguard Worker 	const size_t write_header_size = sizeof(struct fuse_in_header) +
2909*9e564957SAndroid Build Coastguard Worker 		sizeof(struct fuse_write_in);
2910*9e564957SAndroid Build Coastguard Worker 	struct fuse_bufvec bufv = { .buf[0] = *buf, .count = 1 };
2911*9e564957SAndroid Build Coastguard Worker 	struct fuse_bufvec tmpbuf = FUSE_BUFVEC_INIT(write_header_size);
2912*9e564957SAndroid Build Coastguard Worker 	struct fuse_in_header *in;
2913*9e564957SAndroid Build Coastguard Worker 	const void *inarg;
2914*9e564957SAndroid Build Coastguard Worker 	struct fuse_req *req;
2915*9e564957SAndroid Build Coastguard Worker 	void *mbuf = NULL;
2916*9e564957SAndroid Build Coastguard Worker 	int err;
2917*9e564957SAndroid Build Coastguard Worker 	int res;
2918*9e564957SAndroid Build Coastguard Worker 	int opcode_filter;
2919*9e564957SAndroid Build Coastguard Worker 
2920*9e564957SAndroid Build Coastguard Worker 	if (buf->flags & FUSE_BUF_IS_FD) {
2921*9e564957SAndroid Build Coastguard Worker 		if (buf->size < tmpbuf.buf[0].size)
2922*9e564957SAndroid Build Coastguard Worker 			tmpbuf.buf[0].size = buf->size;
2923*9e564957SAndroid Build Coastguard Worker 
2924*9e564957SAndroid Build Coastguard Worker 		mbuf = malloc(tmpbuf.buf[0].size);
2925*9e564957SAndroid Build Coastguard Worker 		if (mbuf == NULL) {
2926*9e564957SAndroid Build Coastguard Worker 			fuse_log(FUSE_LOG_ERR, "fuse: failed to allocate header\n");
2927*9e564957SAndroid Build Coastguard Worker 			goto clear_pipe;
2928*9e564957SAndroid Build Coastguard Worker 		}
2929*9e564957SAndroid Build Coastguard Worker 		tmpbuf.buf[0].mem = mbuf;
2930*9e564957SAndroid Build Coastguard Worker 
2931*9e564957SAndroid Build Coastguard Worker 		res = fuse_ll_copy_from_pipe(&tmpbuf, &bufv);
2932*9e564957SAndroid Build Coastguard Worker 		if (res < 0)
2933*9e564957SAndroid Build Coastguard Worker 			goto clear_pipe;
2934*9e564957SAndroid Build Coastguard Worker 
2935*9e564957SAndroid Build Coastguard Worker 		in = mbuf;
2936*9e564957SAndroid Build Coastguard Worker 	} else {
2937*9e564957SAndroid Build Coastguard Worker 		in = buf->mem;
2938*9e564957SAndroid Build Coastguard Worker 	}
2939*9e564957SAndroid Build Coastguard Worker 
2940*9e564957SAndroid Build Coastguard Worker 	/* Cleanup opcode most significant bits used by FUSE BPF */
2941*9e564957SAndroid Build Coastguard Worker 	opcode_filter = in->opcode & ~FUSE_OPCODE_FILTER;
2942*9e564957SAndroid Build Coastguard Worker 	in->opcode &= FUSE_OPCODE_FILTER;
2943*9e564957SAndroid Build Coastguard Worker 
2944*9e564957SAndroid Build Coastguard Worker 	if (se->debug) {
2945*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_DEBUG,
2946*9e564957SAndroid Build Coastguard Worker 			"unique: %llu, opcode: %s (%i), opcode filter: %s (%i), nodeid: %llu, insize: %zu, pid: %u\n",
2947*9e564957SAndroid Build Coastguard Worker 			(unsigned long long) in->unique,
2948*9e564957SAndroid Build Coastguard Worker 			opname((enum fuse_opcode) in->opcode), in->opcode,
2949*9e564957SAndroid Build Coastguard Worker 			opfiltername((enum fuse_opcode) opcode_filter), opcode_filter,
2950*9e564957SAndroid Build Coastguard Worker 			(unsigned long long) in->nodeid, buf->size, in->pid);
2951*9e564957SAndroid Build Coastguard Worker 	}
2952*9e564957SAndroid Build Coastguard Worker 
2953*9e564957SAndroid Build Coastguard Worker 	req = fuse_ll_alloc_req(se);
2954*9e564957SAndroid Build Coastguard Worker 	if (req == NULL) {
2955*9e564957SAndroid Build Coastguard Worker 		struct fuse_out_header out = {
2956*9e564957SAndroid Build Coastguard Worker 			.unique = in->unique,
2957*9e564957SAndroid Build Coastguard Worker 			.error = -ENOMEM,
2958*9e564957SAndroid Build Coastguard Worker 		};
2959*9e564957SAndroid Build Coastguard Worker 		struct iovec iov = {
2960*9e564957SAndroid Build Coastguard Worker 			.iov_base = &out,
2961*9e564957SAndroid Build Coastguard Worker 			.iov_len = sizeof(struct fuse_out_header),
2962*9e564957SAndroid Build Coastguard Worker 		};
2963*9e564957SAndroid Build Coastguard Worker 
2964*9e564957SAndroid Build Coastguard Worker 		fuse_send_msg(se, ch, &iov, 1);
2965*9e564957SAndroid Build Coastguard Worker 		goto clear_pipe;
2966*9e564957SAndroid Build Coastguard Worker 	}
2967*9e564957SAndroid Build Coastguard Worker 
2968*9e564957SAndroid Build Coastguard Worker 	req->unique = in->unique;
2969*9e564957SAndroid Build Coastguard Worker 	req->ctx.uid = in->uid;
2970*9e564957SAndroid Build Coastguard Worker 	req->ctx.gid = in->gid;
2971*9e564957SAndroid Build Coastguard Worker 	req->ctx.pid = in->pid;
2972*9e564957SAndroid Build Coastguard Worker 	req->ch = ch ? fuse_chan_get(ch) : NULL;
2973*9e564957SAndroid Build Coastguard Worker 
2974*9e564957SAndroid Build Coastguard Worker 	err = EIO;
2975*9e564957SAndroid Build Coastguard Worker 	if (!se->got_init) {
2976*9e564957SAndroid Build Coastguard Worker 		enum fuse_opcode expected;
2977*9e564957SAndroid Build Coastguard Worker 
2978*9e564957SAndroid Build Coastguard Worker 		expected = se->cuse_data ? CUSE_INIT : FUSE_INIT;
2979*9e564957SAndroid Build Coastguard Worker 		if (in->opcode != expected)
2980*9e564957SAndroid Build Coastguard Worker 			goto reply_err;
2981*9e564957SAndroid Build Coastguard Worker 	} else if (in->opcode == FUSE_INIT || in->opcode == CUSE_INIT)
2982*9e564957SAndroid Build Coastguard Worker 		goto reply_err;
2983*9e564957SAndroid Build Coastguard Worker 
2984*9e564957SAndroid Build Coastguard Worker 	err = EACCES;
2985*9e564957SAndroid Build Coastguard Worker 	/* Implement -o allow_root */
2986*9e564957SAndroid Build Coastguard Worker 	if (se->deny_others && in->uid != se->owner && in->uid != 0 &&
2987*9e564957SAndroid Build Coastguard Worker 		 in->opcode != FUSE_INIT && in->opcode != FUSE_READ &&
2988*9e564957SAndroid Build Coastguard Worker 		 in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC &&
2989*9e564957SAndroid Build Coastguard Worker 		 in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR &&
2990*9e564957SAndroid Build Coastguard Worker 		 in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR &&
2991*9e564957SAndroid Build Coastguard Worker 		 in->opcode != FUSE_NOTIFY_REPLY &&
2992*9e564957SAndroid Build Coastguard Worker 		 in->opcode != FUSE_READDIRPLUS)
2993*9e564957SAndroid Build Coastguard Worker 		goto reply_err;
2994*9e564957SAndroid Build Coastguard Worker 
2995*9e564957SAndroid Build Coastguard Worker 	err = ENOSYS;
2996*9e564957SAndroid Build Coastguard Worker 	if (in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func)
2997*9e564957SAndroid Build Coastguard Worker 		goto reply_err;
2998*9e564957SAndroid Build Coastguard Worker 	if (in->opcode != FUSE_INTERRUPT) {
2999*9e564957SAndroid Build Coastguard Worker 		struct fuse_req *intr;
3000*9e564957SAndroid Build Coastguard Worker 		pthread_mutex_lock(&se->lock);
3001*9e564957SAndroid Build Coastguard Worker 		intr = check_interrupt(se, req);
3002*9e564957SAndroid Build Coastguard Worker 		list_add_req(req, &se->list);
3003*9e564957SAndroid Build Coastguard Worker 		pthread_mutex_unlock(&se->lock);
3004*9e564957SAndroid Build Coastguard Worker 		if (intr)
3005*9e564957SAndroid Build Coastguard Worker 			fuse_reply_err(intr, EAGAIN);
3006*9e564957SAndroid Build Coastguard Worker 	}
3007*9e564957SAndroid Build Coastguard Worker 
3008*9e564957SAndroid Build Coastguard Worker 	if ((buf->flags & FUSE_BUF_IS_FD) && write_header_size < buf->size &&
3009*9e564957SAndroid Build Coastguard Worker 	    (in->opcode != FUSE_WRITE || !se->op.write_buf) &&
3010*9e564957SAndroid Build Coastguard Worker 	    in->opcode != FUSE_NOTIFY_REPLY) {
3011*9e564957SAndroid Build Coastguard Worker 		void *newmbuf;
3012*9e564957SAndroid Build Coastguard Worker 
3013*9e564957SAndroid Build Coastguard Worker 		err = ENOMEM;
3014*9e564957SAndroid Build Coastguard Worker 		newmbuf = realloc(mbuf, buf->size);
3015*9e564957SAndroid Build Coastguard Worker 		if (newmbuf == NULL)
3016*9e564957SAndroid Build Coastguard Worker 			goto reply_err;
3017*9e564957SAndroid Build Coastguard Worker 		mbuf = newmbuf;
3018*9e564957SAndroid Build Coastguard Worker 
3019*9e564957SAndroid Build Coastguard Worker 		tmpbuf = FUSE_BUFVEC_INIT(buf->size - write_header_size);
3020*9e564957SAndroid Build Coastguard Worker 		tmpbuf.buf[0].mem = (char *)mbuf + write_header_size;
3021*9e564957SAndroid Build Coastguard Worker 
3022*9e564957SAndroid Build Coastguard Worker 		res = fuse_ll_copy_from_pipe(&tmpbuf, &bufv);
3023*9e564957SAndroid Build Coastguard Worker 		err = -res;
3024*9e564957SAndroid Build Coastguard Worker 		if (res < 0)
3025*9e564957SAndroid Build Coastguard Worker 			goto reply_err;
3026*9e564957SAndroid Build Coastguard Worker 
3027*9e564957SAndroid Build Coastguard Worker 		in = mbuf;
3028*9e564957SAndroid Build Coastguard Worker 	}
3029*9e564957SAndroid Build Coastguard Worker 
3030*9e564957SAndroid Build Coastguard Worker 	inarg = (void *) &in[1];
3031*9e564957SAndroid Build Coastguard Worker 	if (in->opcode == FUSE_WRITE && se->op.write_buf)
3032*9e564957SAndroid Build Coastguard Worker 		do_write_buf(req, in->nodeid, inarg, buf);
3033*9e564957SAndroid Build Coastguard Worker 	else if (in->opcode == FUSE_NOTIFY_REPLY)
3034*9e564957SAndroid Build Coastguard Worker 		do_notify_reply(req, in->nodeid, inarg, buf);
3035*9e564957SAndroid Build Coastguard Worker 	else if (!opcode_filter)
3036*9e564957SAndroid Build Coastguard Worker 		fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg);
3037*9e564957SAndroid Build Coastguard Worker 	else if (opcode_filter == FUSE_PREFILTER && fuse_ll_prefilter_ops[in->opcode].func)
3038*9e564957SAndroid Build Coastguard Worker 	  fuse_ll_prefilter_ops[in->opcode].func(req, in->nodeid, inarg);
3039*9e564957SAndroid Build Coastguard Worker 	else if (opcode_filter == FUSE_POSTFILTER
3040*9e564957SAndroid Build Coastguard Worker 			&& fuse_ll_postfilter_ops[in->opcode].func)
3041*9e564957SAndroid Build Coastguard Worker 		fuse_ll_postfilter_ops[in->opcode].func(
3042*9e564957SAndroid Build Coastguard Worker 				req, in->nodeid, in->error_in, inarg,
3043*9e564957SAndroid Build Coastguard Worker 				buf->size - sizeof(struct fuse_in_header));
3044*9e564957SAndroid Build Coastguard Worker 	else {
3045*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "Bad opcode");
3046*9e564957SAndroid Build Coastguard Worker 		err = ENOSYS;
3047*9e564957SAndroid Build Coastguard Worker 		goto reply_err;
3048*9e564957SAndroid Build Coastguard Worker 	}
3049*9e564957SAndroid Build Coastguard Worker 
3050*9e564957SAndroid Build Coastguard Worker out_free:
3051*9e564957SAndroid Build Coastguard Worker 	free(mbuf);
3052*9e564957SAndroid Build Coastguard Worker 	return;
3053*9e564957SAndroid Build Coastguard Worker 
3054*9e564957SAndroid Build Coastguard Worker reply_err:
3055*9e564957SAndroid Build Coastguard Worker 	fuse_reply_err(req, err);
3056*9e564957SAndroid Build Coastguard Worker clear_pipe:
3057*9e564957SAndroid Build Coastguard Worker 	if (buf->flags & FUSE_BUF_IS_FD)
3058*9e564957SAndroid Build Coastguard Worker 		fuse_ll_clear_pipe(se);
3059*9e564957SAndroid Build Coastguard Worker 	goto out_free;
3060*9e564957SAndroid Build Coastguard Worker }
3061*9e564957SAndroid Build Coastguard Worker 
3062*9e564957SAndroid Build Coastguard Worker #define LL_OPTION(n,o,v) \
3063*9e564957SAndroid Build Coastguard Worker 	{ n, offsetof(struct fuse_session, o), v }
3064*9e564957SAndroid Build Coastguard Worker 
3065*9e564957SAndroid Build Coastguard Worker static const struct fuse_opt fuse_ll_opts[] = {
3066*9e564957SAndroid Build Coastguard Worker 	LL_OPTION("debug", debug, 1),
3067*9e564957SAndroid Build Coastguard Worker 	LL_OPTION("-d", debug, 1),
3068*9e564957SAndroid Build Coastguard Worker 	LL_OPTION("--debug", debug, 1),
3069*9e564957SAndroid Build Coastguard Worker 	LL_OPTION("allow_root", deny_others, 1),
3070*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_END
3071*9e564957SAndroid Build Coastguard Worker };
3072*9e564957SAndroid Build Coastguard Worker 
3073*9e564957SAndroid Build Coastguard Worker void fuse_lowlevel_version(void)
3074*9e564957SAndroid Build Coastguard Worker {
3075*9e564957SAndroid Build Coastguard Worker 	printf("using FUSE kernel interface version %i.%i\n",
3076*9e564957SAndroid Build Coastguard Worker 	       FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
3077*9e564957SAndroid Build Coastguard Worker 	fuse_mount_version();
3078*9e564957SAndroid Build Coastguard Worker }
3079*9e564957SAndroid Build Coastguard Worker 
3080*9e564957SAndroid Build Coastguard Worker void fuse_lowlevel_help(void)
3081*9e564957SAndroid Build Coastguard Worker {
3082*9e564957SAndroid Build Coastguard Worker 	/* These are not all options, but the ones that are
3083*9e564957SAndroid Build Coastguard Worker 	   potentially of interest to an end-user */
3084*9e564957SAndroid Build Coastguard Worker 	printf(
3085*9e564957SAndroid Build Coastguard Worker "    -o allow_other         allow access by all users\n"
3086*9e564957SAndroid Build Coastguard Worker "    -o allow_root          allow access by root\n"
3087*9e564957SAndroid Build Coastguard Worker "    -o auto_unmount        auto unmount on process termination\n");
3088*9e564957SAndroid Build Coastguard Worker }
3089*9e564957SAndroid Build Coastguard Worker 
3090*9e564957SAndroid Build Coastguard Worker void fuse_session_destroy(struct fuse_session *se)
3091*9e564957SAndroid Build Coastguard Worker {
3092*9e564957SAndroid Build Coastguard Worker 	struct fuse_ll_pipe *llp;
3093*9e564957SAndroid Build Coastguard Worker 
3094*9e564957SAndroid Build Coastguard Worker 	if (se->got_init && !se->got_destroy) {
3095*9e564957SAndroid Build Coastguard Worker 		if (se->op.destroy)
3096*9e564957SAndroid Build Coastguard Worker 			se->op.destroy(se->userdata);
3097*9e564957SAndroid Build Coastguard Worker 	}
3098*9e564957SAndroid Build Coastguard Worker 	llp = pthread_getspecific(se->pipe_key);
3099*9e564957SAndroid Build Coastguard Worker 	if (llp != NULL)
3100*9e564957SAndroid Build Coastguard Worker 		fuse_ll_pipe_free(llp);
3101*9e564957SAndroid Build Coastguard Worker 	pthread_key_delete(se->pipe_key);
3102*9e564957SAndroid Build Coastguard Worker 	pthread_mutex_destroy(&se->lock);
3103*9e564957SAndroid Build Coastguard Worker 	free(se->cuse_data);
3104*9e564957SAndroid Build Coastguard Worker 	if (se->fd != -1)
3105*9e564957SAndroid Build Coastguard Worker 		close(se->fd);
3106*9e564957SAndroid Build Coastguard Worker 	if (se->io != NULL)
3107*9e564957SAndroid Build Coastguard Worker 		free(se->io);
3108*9e564957SAndroid Build Coastguard Worker 	destroy_mount_opts(se->mo);
3109*9e564957SAndroid Build Coastguard Worker 	free(se);
3110*9e564957SAndroid Build Coastguard Worker }
3111*9e564957SAndroid Build Coastguard Worker 
3112*9e564957SAndroid Build Coastguard Worker 
3113*9e564957SAndroid Build Coastguard Worker static void fuse_ll_pipe_destructor(void *data)
3114*9e564957SAndroid Build Coastguard Worker {
3115*9e564957SAndroid Build Coastguard Worker 	struct fuse_ll_pipe *llp = data;
3116*9e564957SAndroid Build Coastguard Worker 	fuse_ll_pipe_free(llp);
3117*9e564957SAndroid Build Coastguard Worker }
3118*9e564957SAndroid Build Coastguard Worker 
3119*9e564957SAndroid Build Coastguard Worker int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf)
3120*9e564957SAndroid Build Coastguard Worker {
3121*9e564957SAndroid Build Coastguard Worker 	return fuse_session_receive_buf_int(se, buf, NULL);
3122*9e564957SAndroid Build Coastguard Worker }
3123*9e564957SAndroid Build Coastguard Worker 
3124*9e564957SAndroid Build Coastguard Worker int fuse_session_receive_buf_int(struct fuse_session *se, struct fuse_buf *buf,
3125*9e564957SAndroid Build Coastguard Worker 				 struct fuse_chan *ch)
3126*9e564957SAndroid Build Coastguard Worker {
3127*9e564957SAndroid Build Coastguard Worker 	int err;
3128*9e564957SAndroid Build Coastguard Worker 	ssize_t res;
3129*9e564957SAndroid Build Coastguard Worker #ifdef HAVE_SPLICE
3130*9e564957SAndroid Build Coastguard Worker 	size_t bufsize = se->bufsize;
3131*9e564957SAndroid Build Coastguard Worker 	struct fuse_ll_pipe *llp;
3132*9e564957SAndroid Build Coastguard Worker 	struct fuse_buf tmpbuf;
3133*9e564957SAndroid Build Coastguard Worker 
3134*9e564957SAndroid Build Coastguard Worker 	if (se->conn.proto_minor < 14 || !(se->conn.want & FUSE_CAP_SPLICE_READ))
3135*9e564957SAndroid Build Coastguard Worker 		goto fallback;
3136*9e564957SAndroid Build Coastguard Worker 
3137*9e564957SAndroid Build Coastguard Worker 	llp = fuse_ll_get_pipe(se);
3138*9e564957SAndroid Build Coastguard Worker 	if (llp == NULL)
3139*9e564957SAndroid Build Coastguard Worker 		goto fallback;
3140*9e564957SAndroid Build Coastguard Worker 
3141*9e564957SAndroid Build Coastguard Worker 	if (llp->size < bufsize) {
3142*9e564957SAndroid Build Coastguard Worker 		if (llp->can_grow) {
3143*9e564957SAndroid Build Coastguard Worker 			res = fcntl(llp->pipe[0], F_SETPIPE_SZ, bufsize);
3144*9e564957SAndroid Build Coastguard Worker 			if (res == -1) {
3145*9e564957SAndroid Build Coastguard Worker 				llp->can_grow = 0;
3146*9e564957SAndroid Build Coastguard Worker 				res = grow_pipe_to_max(llp->pipe[0]);
3147*9e564957SAndroid Build Coastguard Worker 				if (res > 0)
3148*9e564957SAndroid Build Coastguard Worker 					llp->size = res;
3149*9e564957SAndroid Build Coastguard Worker 				goto fallback;
3150*9e564957SAndroid Build Coastguard Worker 			}
3151*9e564957SAndroid Build Coastguard Worker 			llp->size = res;
3152*9e564957SAndroid Build Coastguard Worker 		}
3153*9e564957SAndroid Build Coastguard Worker 		if (llp->size < bufsize)
3154*9e564957SAndroid Build Coastguard Worker 			goto fallback;
3155*9e564957SAndroid Build Coastguard Worker 	}
3156*9e564957SAndroid Build Coastguard Worker 
3157*9e564957SAndroid Build Coastguard Worker 	if (se->io != NULL && se->io->splice_receive != NULL) {
3158*9e564957SAndroid Build Coastguard Worker 		res = se->io->splice_receive(ch ? ch->fd : se->fd, NULL,
3159*9e564957SAndroid Build Coastguard Worker 						     llp->pipe[1], NULL, bufsize, 0,
3160*9e564957SAndroid Build Coastguard Worker 						     se->userdata);
3161*9e564957SAndroid Build Coastguard Worker 	} else {
3162*9e564957SAndroid Build Coastguard Worker 		res = splice(ch ? ch->fd : se->fd, NULL, llp->pipe[1], NULL,
3163*9e564957SAndroid Build Coastguard Worker 				 bufsize, 0);
3164*9e564957SAndroid Build Coastguard Worker 	}
3165*9e564957SAndroid Build Coastguard Worker 	err = errno;
3166*9e564957SAndroid Build Coastguard Worker 
3167*9e564957SAndroid Build Coastguard Worker 	if (fuse_session_exited(se))
3168*9e564957SAndroid Build Coastguard Worker 		return 0;
3169*9e564957SAndroid Build Coastguard Worker 
3170*9e564957SAndroid Build Coastguard Worker 	if (res == -1) {
3171*9e564957SAndroid Build Coastguard Worker 		if (err == ENODEV) {
3172*9e564957SAndroid Build Coastguard Worker 			/* Filesystem was unmounted, or connection was aborted
3173*9e564957SAndroid Build Coastguard Worker 			   via /sys/fs/fuse/connections */
3174*9e564957SAndroid Build Coastguard Worker 			fuse_session_exit(se);
3175*9e564957SAndroid Build Coastguard Worker 			return 0;
3176*9e564957SAndroid Build Coastguard Worker 		}
3177*9e564957SAndroid Build Coastguard Worker 		if (err != EINTR && err != EAGAIN)
3178*9e564957SAndroid Build Coastguard Worker 			perror("fuse: splice from device");
3179*9e564957SAndroid Build Coastguard Worker 		return -err;
3180*9e564957SAndroid Build Coastguard Worker 	}
3181*9e564957SAndroid Build Coastguard Worker 
3182*9e564957SAndroid Build Coastguard Worker 	if (res < sizeof(struct fuse_in_header)) {
3183*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "short splice from fuse device\n");
3184*9e564957SAndroid Build Coastguard Worker 		return -EIO;
3185*9e564957SAndroid Build Coastguard Worker 	}
3186*9e564957SAndroid Build Coastguard Worker 
3187*9e564957SAndroid Build Coastguard Worker 	tmpbuf = (struct fuse_buf) {
3188*9e564957SAndroid Build Coastguard Worker 		.size = res,
3189*9e564957SAndroid Build Coastguard Worker 		.flags = FUSE_BUF_IS_FD,
3190*9e564957SAndroid Build Coastguard Worker 		.fd = llp->pipe[0],
3191*9e564957SAndroid Build Coastguard Worker 	};
3192*9e564957SAndroid Build Coastguard Worker 
3193*9e564957SAndroid Build Coastguard Worker 	/*
3194*9e564957SAndroid Build Coastguard Worker 	 * Don't bother with zero copy for small requests.
3195*9e564957SAndroid Build Coastguard Worker 	 * fuse_loop_mt() needs to check for FORGET so this more than
3196*9e564957SAndroid Build Coastguard Worker 	 * just an optimization.
3197*9e564957SAndroid Build Coastguard Worker 	 */
3198*9e564957SAndroid Build Coastguard Worker 	if (res < sizeof(struct fuse_in_header) +
3199*9e564957SAndroid Build Coastguard Worker 	    sizeof(struct fuse_write_in) + pagesize) {
3200*9e564957SAndroid Build Coastguard Worker 		struct fuse_bufvec src = { .buf[0] = tmpbuf, .count = 1 };
3201*9e564957SAndroid Build Coastguard Worker 		struct fuse_bufvec dst = { .count = 1 };
3202*9e564957SAndroid Build Coastguard Worker 
3203*9e564957SAndroid Build Coastguard Worker 		if (!buf->mem) {
3204*9e564957SAndroid Build Coastguard Worker 			buf->mem = malloc(se->bufsize);
3205*9e564957SAndroid Build Coastguard Worker 			if (!buf->mem) {
3206*9e564957SAndroid Build Coastguard Worker 				fuse_log(FUSE_LOG_ERR,
3207*9e564957SAndroid Build Coastguard Worker 					"fuse: failed to allocate read buffer\n");
3208*9e564957SAndroid Build Coastguard Worker 				return -ENOMEM;
3209*9e564957SAndroid Build Coastguard Worker 			}
3210*9e564957SAndroid Build Coastguard Worker 		}
3211*9e564957SAndroid Build Coastguard Worker 		buf->size = se->bufsize;
3212*9e564957SAndroid Build Coastguard Worker 		buf->flags = 0;
3213*9e564957SAndroid Build Coastguard Worker 		dst.buf[0] = *buf;
3214*9e564957SAndroid Build Coastguard Worker 
3215*9e564957SAndroid Build Coastguard Worker 		res = fuse_buf_copy(&dst, &src, 0);
3216*9e564957SAndroid Build Coastguard Worker 		if (res < 0) {
3217*9e564957SAndroid Build Coastguard Worker 			fuse_log(FUSE_LOG_ERR, "fuse: copy from pipe: %s\n",
3218*9e564957SAndroid Build Coastguard Worker 				strerror(-res));
3219*9e564957SAndroid Build Coastguard Worker 			fuse_ll_clear_pipe(se);
3220*9e564957SAndroid Build Coastguard Worker 			return res;
3221*9e564957SAndroid Build Coastguard Worker 		}
3222*9e564957SAndroid Build Coastguard Worker 		if (res < tmpbuf.size) {
3223*9e564957SAndroid Build Coastguard Worker 			fuse_log(FUSE_LOG_ERR, "fuse: copy from pipe: short read\n");
3224*9e564957SAndroid Build Coastguard Worker 			fuse_ll_clear_pipe(se);
3225*9e564957SAndroid Build Coastguard Worker 			return -EIO;
3226*9e564957SAndroid Build Coastguard Worker 		}
3227*9e564957SAndroid Build Coastguard Worker 		assert(res == tmpbuf.size);
3228*9e564957SAndroid Build Coastguard Worker 
3229*9e564957SAndroid Build Coastguard Worker 	} else {
3230*9e564957SAndroid Build Coastguard Worker 		/* Don't overwrite buf->mem, as that would cause a leak */
3231*9e564957SAndroid Build Coastguard Worker 		buf->fd = tmpbuf.fd;
3232*9e564957SAndroid Build Coastguard Worker 		buf->flags = tmpbuf.flags;
3233*9e564957SAndroid Build Coastguard Worker 	}
3234*9e564957SAndroid Build Coastguard Worker 	buf->size = tmpbuf.size;
3235*9e564957SAndroid Build Coastguard Worker 
3236*9e564957SAndroid Build Coastguard Worker 	return res;
3237*9e564957SAndroid Build Coastguard Worker 
3238*9e564957SAndroid Build Coastguard Worker fallback:
3239*9e564957SAndroid Build Coastguard Worker #endif
3240*9e564957SAndroid Build Coastguard Worker 	if (!buf->mem) {
3241*9e564957SAndroid Build Coastguard Worker 		buf->mem = malloc(se->bufsize);
3242*9e564957SAndroid Build Coastguard Worker 		if (!buf->mem) {
3243*9e564957SAndroid Build Coastguard Worker 			fuse_log(FUSE_LOG_ERR,
3244*9e564957SAndroid Build Coastguard Worker 				"fuse: failed to allocate read buffer\n");
3245*9e564957SAndroid Build Coastguard Worker 			return -ENOMEM;
3246*9e564957SAndroid Build Coastguard Worker 		}
3247*9e564957SAndroid Build Coastguard Worker 	}
3248*9e564957SAndroid Build Coastguard Worker 
3249*9e564957SAndroid Build Coastguard Worker restart:
3250*9e564957SAndroid Build Coastguard Worker 	if (se->io != NULL) {
3251*9e564957SAndroid Build Coastguard Worker 		/* se->io->read is never NULL if se->io is not NULL as
3252*9e564957SAndroid Build Coastguard Worker 		specified by fuse_session_custom_io()*/
3253*9e564957SAndroid Build Coastguard Worker 		res = se->io->read(ch ? ch->fd : se->fd, buf->mem, se->bufsize,
3254*9e564957SAndroid Build Coastguard Worker 					 se->userdata);
3255*9e564957SAndroid Build Coastguard Worker 	} else {
3256*9e564957SAndroid Build Coastguard Worker 		res = read(ch ? ch->fd : se->fd, buf->mem, se->bufsize);
3257*9e564957SAndroid Build Coastguard Worker 	}
3258*9e564957SAndroid Build Coastguard Worker 	err = errno;
3259*9e564957SAndroid Build Coastguard Worker 
3260*9e564957SAndroid Build Coastguard Worker 	if (fuse_session_exited(se))
3261*9e564957SAndroid Build Coastguard Worker 		return 0;
3262*9e564957SAndroid Build Coastguard Worker 	if (res == -1) {
3263*9e564957SAndroid Build Coastguard Worker 		/* ENOENT means the operation was interrupted, it's safe
3264*9e564957SAndroid Build Coastguard Worker 		   to restart */
3265*9e564957SAndroid Build Coastguard Worker 		if (err == ENOENT)
3266*9e564957SAndroid Build Coastguard Worker 			goto restart;
3267*9e564957SAndroid Build Coastguard Worker 
3268*9e564957SAndroid Build Coastguard Worker 		if (err == ENODEV) {
3269*9e564957SAndroid Build Coastguard Worker 			/* Filesystem was unmounted, or connection was aborted
3270*9e564957SAndroid Build Coastguard Worker 			   via /sys/fs/fuse/connections */
3271*9e564957SAndroid Build Coastguard Worker 			fuse_session_exit(se);
3272*9e564957SAndroid Build Coastguard Worker 			return 0;
3273*9e564957SAndroid Build Coastguard Worker 		}
3274*9e564957SAndroid Build Coastguard Worker 		/* Errors occurring during normal operation: EINTR (read
3275*9e564957SAndroid Build Coastguard Worker 		   interrupted), EAGAIN (nonblocking I/O), ENODEV (filesystem
3276*9e564957SAndroid Build Coastguard Worker 		   umounted) */
3277*9e564957SAndroid Build Coastguard Worker 		if (err != EINTR && err != EAGAIN)
3278*9e564957SAndroid Build Coastguard Worker 			perror("fuse: reading device");
3279*9e564957SAndroid Build Coastguard Worker 		return -err;
3280*9e564957SAndroid Build Coastguard Worker 	}
3281*9e564957SAndroid Build Coastguard Worker 	if ((size_t) res < sizeof(struct fuse_in_header)) {
3282*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "short read on fuse device\n");
3283*9e564957SAndroid Build Coastguard Worker 		return -EIO;
3284*9e564957SAndroid Build Coastguard Worker 	}
3285*9e564957SAndroid Build Coastguard Worker 
3286*9e564957SAndroid Build Coastguard Worker 	buf->size = res;
3287*9e564957SAndroid Build Coastguard Worker 
3288*9e564957SAndroid Build Coastguard Worker 	return res;
3289*9e564957SAndroid Build Coastguard Worker }
3290*9e564957SAndroid Build Coastguard Worker 
3291*9e564957SAndroid Build Coastguard Worker FUSE_SYMVER("_fuse_session_new_317", "_fuse_session_new@@FUSE_3.17")
3292*9e564957SAndroid Build Coastguard Worker struct fuse_session *_fuse_session_new_317(struct fuse_args *args,
3293*9e564957SAndroid Build Coastguard Worker 					  const struct fuse_lowlevel_ops *op,
3294*9e564957SAndroid Build Coastguard Worker 					  size_t op_size,
3295*9e564957SAndroid Build Coastguard Worker 					  struct libfuse_version *version,
3296*9e564957SAndroid Build Coastguard Worker 					  void *userdata)
3297*9e564957SAndroid Build Coastguard Worker {
3298*9e564957SAndroid Build Coastguard Worker 	int err;
3299*9e564957SAndroid Build Coastguard Worker 	struct fuse_session *se;
3300*9e564957SAndroid Build Coastguard Worker 	struct mount_opts *mo;
3301*9e564957SAndroid Build Coastguard Worker 
3302*9e564957SAndroid Build Coastguard Worker 	if (sizeof(struct fuse_lowlevel_ops) < op_size) {
3303*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: warning: library too old, some operations may not work\n");
3304*9e564957SAndroid Build Coastguard Worker 		op_size = sizeof(struct fuse_lowlevel_ops);
3305*9e564957SAndroid Build Coastguard Worker 	}
3306*9e564957SAndroid Build Coastguard Worker 
3307*9e564957SAndroid Build Coastguard Worker 	if (args->argc == 0) {
3308*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: empty argv passed to fuse_session_new().\n");
3309*9e564957SAndroid Build Coastguard Worker 		return NULL;
3310*9e564957SAndroid Build Coastguard Worker 	}
3311*9e564957SAndroid Build Coastguard Worker 
3312*9e564957SAndroid Build Coastguard Worker 	se = (struct fuse_session *) calloc(1, sizeof(struct fuse_session));
3313*9e564957SAndroid Build Coastguard Worker 	if (se == NULL) {
3314*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: failed to allocate fuse object\n");
3315*9e564957SAndroid Build Coastguard Worker 		goto out1;
3316*9e564957SAndroid Build Coastguard Worker 	}
3317*9e564957SAndroid Build Coastguard Worker 	se->fd = -1;
3318*9e564957SAndroid Build Coastguard Worker 	se->conn.max_write = UINT_MAX;
3319*9e564957SAndroid Build Coastguard Worker 	se->conn.max_readahead = UINT_MAX;
3320*9e564957SAndroid Build Coastguard Worker 
3321*9e564957SAndroid Build Coastguard Worker 	/* Parse options */
3322*9e564957SAndroid Build Coastguard Worker 	if(fuse_opt_parse(args, se, fuse_ll_opts, NULL) == -1)
3323*9e564957SAndroid Build Coastguard Worker 		goto out2;
3324*9e564957SAndroid Build Coastguard Worker 	if(se->deny_others) {
3325*9e564957SAndroid Build Coastguard Worker 		/* Allowing access only by root is done by instructing
3326*9e564957SAndroid Build Coastguard Worker 		 * kernel to allow access by everyone, and then restricting
3327*9e564957SAndroid Build Coastguard Worker 		 * access to root and mountpoint owner in libfuse.
3328*9e564957SAndroid Build Coastguard Worker 		 */
3329*9e564957SAndroid Build Coastguard Worker 		// We may be adding the option a second time, but
3330*9e564957SAndroid Build Coastguard Worker 		// that doesn't hurt.
3331*9e564957SAndroid Build Coastguard Worker 		if(fuse_opt_add_arg(args, "-oallow_other") == -1)
3332*9e564957SAndroid Build Coastguard Worker 			goto out2;
3333*9e564957SAndroid Build Coastguard Worker 	}
3334*9e564957SAndroid Build Coastguard Worker 	mo = parse_mount_opts(args);
3335*9e564957SAndroid Build Coastguard Worker 	if (mo == NULL)
3336*9e564957SAndroid Build Coastguard Worker 		goto out3;
3337*9e564957SAndroid Build Coastguard Worker 
3338*9e564957SAndroid Build Coastguard Worker 	if(args->argc == 1 &&
3339*9e564957SAndroid Build Coastguard Worker 	   args->argv[0][0] == '-') {
3340*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: warning: argv[0] looks like an option, but "
3341*9e564957SAndroid Build Coastguard Worker 			"will be ignored\n");
3342*9e564957SAndroid Build Coastguard Worker 	} else if (args->argc != 1) {
3343*9e564957SAndroid Build Coastguard Worker 		int i;
3344*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: unknown option(s): `");
3345*9e564957SAndroid Build Coastguard Worker 		for(i = 1; i < args->argc-1; i++)
3346*9e564957SAndroid Build Coastguard Worker 			fuse_log(FUSE_LOG_ERR, "%s ", args->argv[i]);
3347*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "%s'\n", args->argv[i]);
3348*9e564957SAndroid Build Coastguard Worker 		goto out4;
3349*9e564957SAndroid Build Coastguard Worker 	}
3350*9e564957SAndroid Build Coastguard Worker 
3351*9e564957SAndroid Build Coastguard Worker 	if (se->debug)
3352*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_DEBUG, "FUSE library version: %s\n", PACKAGE_VERSION);
3353*9e564957SAndroid Build Coastguard Worker 
3354*9e564957SAndroid Build Coastguard Worker 	se->bufsize = FUSE_MAX_MAX_PAGES * getpagesize() +
3355*9e564957SAndroid Build Coastguard Worker 		FUSE_BUFFER_HEADER_SIZE;
3356*9e564957SAndroid Build Coastguard Worker 
3357*9e564957SAndroid Build Coastguard Worker 	list_init_req(&se->list);
3358*9e564957SAndroid Build Coastguard Worker 	list_init_req(&se->interrupts);
3359*9e564957SAndroid Build Coastguard Worker 	list_init_nreq(&se->notify_list);
3360*9e564957SAndroid Build Coastguard Worker 	se->notify_ctr = 1;
3361*9e564957SAndroid Build Coastguard Worker 	pthread_mutex_init(&se->lock, NULL);
3362*9e564957SAndroid Build Coastguard Worker 
3363*9e564957SAndroid Build Coastguard Worker 	err = pthread_key_create(&se->pipe_key, fuse_ll_pipe_destructor);
3364*9e564957SAndroid Build Coastguard Worker 	if (err) {
3365*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: failed to create thread specific key: %s\n",
3366*9e564957SAndroid Build Coastguard Worker 			strerror(err));
3367*9e564957SAndroid Build Coastguard Worker 		goto out5;
3368*9e564957SAndroid Build Coastguard Worker 	}
3369*9e564957SAndroid Build Coastguard Worker 
3370*9e564957SAndroid Build Coastguard Worker 	memcpy(&se->op, op, op_size);
3371*9e564957SAndroid Build Coastguard Worker 	se->owner = getuid();
3372*9e564957SAndroid Build Coastguard Worker 	se->userdata = userdata;
3373*9e564957SAndroid Build Coastguard Worker 
3374*9e564957SAndroid Build Coastguard Worker 	se->mo = mo;
3375*9e564957SAndroid Build Coastguard Worker 
3376*9e564957SAndroid Build Coastguard Worker 	/* Fuse server application should pass the version it was compiled
3377*9e564957SAndroid Build Coastguard Worker 	 * against and pass it. If a libfuse version accidentally introduces an
3378*9e564957SAndroid Build Coastguard Worker 	 * ABI incompatibility, it might be possible to 'fix' that at run time,
3379*9e564957SAndroid Build Coastguard Worker 	 * by checking the version numbers.
3380*9e564957SAndroid Build Coastguard Worker 	 */
3381*9e564957SAndroid Build Coastguard Worker 	se->version = *version;
3382*9e564957SAndroid Build Coastguard Worker 
3383*9e564957SAndroid Build Coastguard Worker 	return se;
3384*9e564957SAndroid Build Coastguard Worker 
3385*9e564957SAndroid Build Coastguard Worker out5:
3386*9e564957SAndroid Build Coastguard Worker 	pthread_mutex_destroy(&se->lock);
3387*9e564957SAndroid Build Coastguard Worker out4:
3388*9e564957SAndroid Build Coastguard Worker 	fuse_opt_free_args(args);
3389*9e564957SAndroid Build Coastguard Worker out3:
3390*9e564957SAndroid Build Coastguard Worker 	if (mo != NULL)
3391*9e564957SAndroid Build Coastguard Worker 		destroy_mount_opts(mo);
3392*9e564957SAndroid Build Coastguard Worker out2:
3393*9e564957SAndroid Build Coastguard Worker 	free(se);
3394*9e564957SAndroid Build Coastguard Worker out1:
3395*9e564957SAndroid Build Coastguard Worker 	return NULL;
3396*9e564957SAndroid Build Coastguard Worker }
3397*9e564957SAndroid Build Coastguard Worker 
3398*9e564957SAndroid Build Coastguard Worker struct fuse_session *fuse_session_new_30(struct fuse_args *args,
3399*9e564957SAndroid Build Coastguard Worker 					  const struct fuse_lowlevel_ops *op,
3400*9e564957SAndroid Build Coastguard Worker 					  size_t op_size,
3401*9e564957SAndroid Build Coastguard Worker 					  void *userdata);
3402*9e564957SAndroid Build Coastguard Worker FUSE_SYMVER("fuse_session_new_30", "fuse_session_new@FUSE_3.0")
3403*9e564957SAndroid Build Coastguard Worker struct fuse_session *fuse_session_new_30(struct fuse_args *args,
3404*9e564957SAndroid Build Coastguard Worker 					  const struct fuse_lowlevel_ops *op,
3405*9e564957SAndroid Build Coastguard Worker 					  size_t op_size,
3406*9e564957SAndroid Build Coastguard Worker 					  void *userdata)
3407*9e564957SAndroid Build Coastguard Worker {
3408*9e564957SAndroid Build Coastguard Worker 	/* unknown version */
3409*9e564957SAndroid Build Coastguard Worker 	struct libfuse_version version = { 0 };
3410*9e564957SAndroid Build Coastguard Worker 
3411*9e564957SAndroid Build Coastguard Worker 	return _fuse_session_new_317(args, op, op_size, &version, userdata);
3412*9e564957SAndroid Build Coastguard Worker }
3413*9e564957SAndroid Build Coastguard Worker 
3414*9e564957SAndroid Build Coastguard Worker int fuse_session_custom_io(struct fuse_session *se, const struct fuse_custom_io *io,
3415*9e564957SAndroid Build Coastguard Worker 			   int fd)
3416*9e564957SAndroid Build Coastguard Worker {
3417*9e564957SAndroid Build Coastguard Worker 	if (fd < 0) {
3418*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "Invalid file descriptor value %d passed to "
3419*9e564957SAndroid Build Coastguard Worker 			"fuse_session_custom_io()\n", fd);
3420*9e564957SAndroid Build Coastguard Worker 		return -EBADF;
3421*9e564957SAndroid Build Coastguard Worker 	}
3422*9e564957SAndroid Build Coastguard Worker 	if (io == NULL) {
3423*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "No custom IO passed to "
3424*9e564957SAndroid Build Coastguard Worker 			"fuse_session_custom_io()\n");
3425*9e564957SAndroid Build Coastguard Worker 		return -EINVAL;
3426*9e564957SAndroid Build Coastguard Worker 	} else if (io->read == NULL || io->writev == NULL) {
3427*9e564957SAndroid Build Coastguard Worker 		/* If the user provides their own file descriptor, we can't
3428*9e564957SAndroid Build Coastguard Worker 		guarantee that the default behavior of the io operations made
3429*9e564957SAndroid Build Coastguard Worker 		in libfuse will function properly. Therefore, we enforce the
3430*9e564957SAndroid Build Coastguard Worker 		user to implement these io operations when using custom io. */
3431*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "io passed to fuse_session_custom_io() must "
3432*9e564957SAndroid Build Coastguard Worker 			"implement both io->read() and io->writev\n");
3433*9e564957SAndroid Build Coastguard Worker 		return -EINVAL;
3434*9e564957SAndroid Build Coastguard Worker 	}
3435*9e564957SAndroid Build Coastguard Worker 
3436*9e564957SAndroid Build Coastguard Worker 	se->io = malloc(sizeof(struct fuse_custom_io));
3437*9e564957SAndroid Build Coastguard Worker 	if (se->io == NULL) {
3438*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "Failed to allocate memory for custom io. "
3439*9e564957SAndroid Build Coastguard Worker 			"Error: %s\n", strerror(errno));
3440*9e564957SAndroid Build Coastguard Worker 		return -errno;
3441*9e564957SAndroid Build Coastguard Worker 	}
3442*9e564957SAndroid Build Coastguard Worker 
3443*9e564957SAndroid Build Coastguard Worker 	se->fd = fd;
3444*9e564957SAndroid Build Coastguard Worker 	*se->io = *io;
3445*9e564957SAndroid Build Coastguard Worker 	return 0;
3446*9e564957SAndroid Build Coastguard Worker }
3447*9e564957SAndroid Build Coastguard Worker 
3448*9e564957SAndroid Build Coastguard Worker int fuse_session_mount(struct fuse_session *se, const char *mountpoint)
3449*9e564957SAndroid Build Coastguard Worker {
3450*9e564957SAndroid Build Coastguard Worker 	int fd;
3451*9e564957SAndroid Build Coastguard Worker 
3452*9e564957SAndroid Build Coastguard Worker 	/*
3453*9e564957SAndroid Build Coastguard Worker 	 * Make sure file descriptors 0, 1 and 2 are open, otherwise chaos
3454*9e564957SAndroid Build Coastguard Worker 	 * would ensue.
3455*9e564957SAndroid Build Coastguard Worker 	 */
3456*9e564957SAndroid Build Coastguard Worker 	do {
3457*9e564957SAndroid Build Coastguard Worker 		fd = open("/dev/null", O_RDWR);
3458*9e564957SAndroid Build Coastguard Worker 		if (fd > 2)
3459*9e564957SAndroid Build Coastguard Worker 			close(fd);
3460*9e564957SAndroid Build Coastguard Worker 	} while (fd >= 0 && fd <= 2);
3461*9e564957SAndroid Build Coastguard Worker 
3462*9e564957SAndroid Build Coastguard Worker 	/*
3463*9e564957SAndroid Build Coastguard Worker 	 * To allow FUSE daemons to run without privileges, the caller may open
3464*9e564957SAndroid Build Coastguard Worker 	 * /dev/fuse before launching the file system and pass on the file
3465*9e564957SAndroid Build Coastguard Worker 	 * descriptor by specifying /dev/fd/N as the mount point. Note that the
3466*9e564957SAndroid Build Coastguard Worker 	 * parent process takes care of performing the mount in this case.
3467*9e564957SAndroid Build Coastguard Worker 	 */
3468*9e564957SAndroid Build Coastguard Worker 	fd = fuse_mnt_parse_fuse_fd(mountpoint);
3469*9e564957SAndroid Build Coastguard Worker 	if (fd != -1) {
3470*9e564957SAndroid Build Coastguard Worker 		if (fcntl(fd, F_GETFD) == -1) {
3471*9e564957SAndroid Build Coastguard Worker 			fuse_log(FUSE_LOG_ERR,
3472*9e564957SAndroid Build Coastguard Worker 				"fuse: Invalid file descriptor /dev/fd/%u\n",
3473*9e564957SAndroid Build Coastguard Worker 				fd);
3474*9e564957SAndroid Build Coastguard Worker 			return -1;
3475*9e564957SAndroid Build Coastguard Worker 		}
3476*9e564957SAndroid Build Coastguard Worker 		se->fd = fd;
3477*9e564957SAndroid Build Coastguard Worker 		return 0;
3478*9e564957SAndroid Build Coastguard Worker 	}
3479*9e564957SAndroid Build Coastguard Worker 
3480*9e564957SAndroid Build Coastguard Worker 	/* Open channel */
3481*9e564957SAndroid Build Coastguard Worker 	fd = fuse_kern_mount(mountpoint, se->mo);
3482*9e564957SAndroid Build Coastguard Worker 	if (fd == -1)
3483*9e564957SAndroid Build Coastguard Worker 		return -1;
3484*9e564957SAndroid Build Coastguard Worker 	se->fd = fd;
3485*9e564957SAndroid Build Coastguard Worker 
3486*9e564957SAndroid Build Coastguard Worker 	/* Save mountpoint */
3487*9e564957SAndroid Build Coastguard Worker 	se->mountpoint = strdup(mountpoint);
3488*9e564957SAndroid Build Coastguard Worker 	if (se->mountpoint == NULL)
3489*9e564957SAndroid Build Coastguard Worker 		goto error_out;
3490*9e564957SAndroid Build Coastguard Worker 
3491*9e564957SAndroid Build Coastguard Worker 	return 0;
3492*9e564957SAndroid Build Coastguard Worker 
3493*9e564957SAndroid Build Coastguard Worker error_out:
3494*9e564957SAndroid Build Coastguard Worker 	fuse_kern_unmount(mountpoint, fd);
3495*9e564957SAndroid Build Coastguard Worker 	return -1;
3496*9e564957SAndroid Build Coastguard Worker }
3497*9e564957SAndroid Build Coastguard Worker 
3498*9e564957SAndroid Build Coastguard Worker int fuse_session_fd(struct fuse_session *se)
3499*9e564957SAndroid Build Coastguard Worker {
3500*9e564957SAndroid Build Coastguard Worker 	return se->fd;
3501*9e564957SAndroid Build Coastguard Worker }
3502*9e564957SAndroid Build Coastguard Worker 
3503*9e564957SAndroid Build Coastguard Worker void fuse_session_unmount(struct fuse_session *se)
3504*9e564957SAndroid Build Coastguard Worker {
3505*9e564957SAndroid Build Coastguard Worker 	if (se->mountpoint != NULL) {
3506*9e564957SAndroid Build Coastguard Worker 		fuse_kern_unmount(se->mountpoint, se->fd);
3507*9e564957SAndroid Build Coastguard Worker 		se->fd = -1;
3508*9e564957SAndroid Build Coastguard Worker 		free(se->mountpoint);
3509*9e564957SAndroid Build Coastguard Worker 		se->mountpoint = NULL;
3510*9e564957SAndroid Build Coastguard Worker 	}
3511*9e564957SAndroid Build Coastguard Worker }
3512*9e564957SAndroid Build Coastguard Worker 
3513*9e564957SAndroid Build Coastguard Worker #ifdef linux
3514*9e564957SAndroid Build Coastguard Worker int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[])
3515*9e564957SAndroid Build Coastguard Worker {
3516*9e564957SAndroid Build Coastguard Worker 	char *buf;
3517*9e564957SAndroid Build Coastguard Worker 	size_t bufsize = 1024;
3518*9e564957SAndroid Build Coastguard Worker 	char path[128];
3519*9e564957SAndroid Build Coastguard Worker 	int ret;
3520*9e564957SAndroid Build Coastguard Worker 	int fd;
3521*9e564957SAndroid Build Coastguard Worker 	unsigned long pid = req->ctx.pid;
3522*9e564957SAndroid Build Coastguard Worker 	char *s;
3523*9e564957SAndroid Build Coastguard Worker 
3524*9e564957SAndroid Build Coastguard Worker 	sprintf(path, "/proc/%lu/task/%lu/status", pid, pid);
3525*9e564957SAndroid Build Coastguard Worker 
3526*9e564957SAndroid Build Coastguard Worker retry:
3527*9e564957SAndroid Build Coastguard Worker 	buf = malloc(bufsize);
3528*9e564957SAndroid Build Coastguard Worker 	if (buf == NULL)
3529*9e564957SAndroid Build Coastguard Worker 		return -ENOMEM;
3530*9e564957SAndroid Build Coastguard Worker 
3531*9e564957SAndroid Build Coastguard Worker 	ret = -EIO;
3532*9e564957SAndroid Build Coastguard Worker 	fd = open(path, O_RDONLY);
3533*9e564957SAndroid Build Coastguard Worker 	if (fd == -1)
3534*9e564957SAndroid Build Coastguard Worker 		goto out_free;
3535*9e564957SAndroid Build Coastguard Worker 
3536*9e564957SAndroid Build Coastguard Worker 	ret = read(fd, buf, bufsize);
3537*9e564957SAndroid Build Coastguard Worker 	close(fd);
3538*9e564957SAndroid Build Coastguard Worker 	if (ret < 0) {
3539*9e564957SAndroid Build Coastguard Worker 		ret = -EIO;
3540*9e564957SAndroid Build Coastguard Worker 		goto out_free;
3541*9e564957SAndroid Build Coastguard Worker 	}
3542*9e564957SAndroid Build Coastguard Worker 
3543*9e564957SAndroid Build Coastguard Worker 	if ((size_t)ret == bufsize) {
3544*9e564957SAndroid Build Coastguard Worker 		free(buf);
3545*9e564957SAndroid Build Coastguard Worker 		bufsize *= 4;
3546*9e564957SAndroid Build Coastguard Worker 		goto retry;
3547*9e564957SAndroid Build Coastguard Worker 	}
3548*9e564957SAndroid Build Coastguard Worker 
3549*9e564957SAndroid Build Coastguard Worker 	ret = -EIO;
3550*9e564957SAndroid Build Coastguard Worker 	s = strstr(buf, "\nGroups:");
3551*9e564957SAndroid Build Coastguard Worker 	if (s == NULL)
3552*9e564957SAndroid Build Coastguard Worker 		goto out_free;
3553*9e564957SAndroid Build Coastguard Worker 
3554*9e564957SAndroid Build Coastguard Worker 	s += 8;
3555*9e564957SAndroid Build Coastguard Worker 	ret = 0;
3556*9e564957SAndroid Build Coastguard Worker 	while (1) {
3557*9e564957SAndroid Build Coastguard Worker 		char *end;
3558*9e564957SAndroid Build Coastguard Worker 		unsigned long val = strtoul(s, &end, 0);
3559*9e564957SAndroid Build Coastguard Worker 		if (end == s)
3560*9e564957SAndroid Build Coastguard Worker 			break;
3561*9e564957SAndroid Build Coastguard Worker 
3562*9e564957SAndroid Build Coastguard Worker 		s = end;
3563*9e564957SAndroid Build Coastguard Worker 		if (ret < size)
3564*9e564957SAndroid Build Coastguard Worker 			list[ret] = val;
3565*9e564957SAndroid Build Coastguard Worker 		ret++;
3566*9e564957SAndroid Build Coastguard Worker 	}
3567*9e564957SAndroid Build Coastguard Worker 
3568*9e564957SAndroid Build Coastguard Worker out_free:
3569*9e564957SAndroid Build Coastguard Worker 	free(buf);
3570*9e564957SAndroid Build Coastguard Worker 	return ret;
3571*9e564957SAndroid Build Coastguard Worker }
3572*9e564957SAndroid Build Coastguard Worker #else /* linux */
3573*9e564957SAndroid Build Coastguard Worker /*
3574*9e564957SAndroid Build Coastguard Worker  * This is currently not implemented on other than Linux...
3575*9e564957SAndroid Build Coastguard Worker  */
3576*9e564957SAndroid Build Coastguard Worker int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[])
3577*9e564957SAndroid Build Coastguard Worker {
3578*9e564957SAndroid Build Coastguard Worker 	(void) req; (void) size; (void) list;
3579*9e564957SAndroid Build Coastguard Worker 	return -ENOSYS;
3580*9e564957SAndroid Build Coastguard Worker }
3581*9e564957SAndroid Build Coastguard Worker #endif
3582*9e564957SAndroid Build Coastguard Worker 
3583*9e564957SAndroid Build Coastguard Worker /* Prevent spurious data race warning - we don't care
3584*9e564957SAndroid Build Coastguard Worker  * about races for this flag */
3585*9e564957SAndroid Build Coastguard Worker __attribute__((no_sanitize_thread))
3586*9e564957SAndroid Build Coastguard Worker void fuse_session_exit(struct fuse_session *se)
3587*9e564957SAndroid Build Coastguard Worker {
3588*9e564957SAndroid Build Coastguard Worker 	se->exited = 1;
3589*9e564957SAndroid Build Coastguard Worker }
3590*9e564957SAndroid Build Coastguard Worker 
3591*9e564957SAndroid Build Coastguard Worker __attribute__((no_sanitize_thread))
3592*9e564957SAndroid Build Coastguard Worker void fuse_session_reset(struct fuse_session *se)
3593*9e564957SAndroid Build Coastguard Worker {
3594*9e564957SAndroid Build Coastguard Worker 	se->exited = 0;
3595*9e564957SAndroid Build Coastguard Worker 	se->error = 0;
3596*9e564957SAndroid Build Coastguard Worker }
3597*9e564957SAndroid Build Coastguard Worker 
3598*9e564957SAndroid Build Coastguard Worker __attribute__((no_sanitize_thread))
3599*9e564957SAndroid Build Coastguard Worker int fuse_session_exited(struct fuse_session *se)
3600*9e564957SAndroid Build Coastguard Worker {
3601*9e564957SAndroid Build Coastguard Worker 	return se->exited;
3602*9e564957SAndroid Build Coastguard Worker }
3603