1 /*
2  * Copyright (C) 2021 Jakub Kruszona-Zawadzki, Core Technology Sp. z o.o.
3  *
4  * This file is part of MooseFS.
5  *
6  * MooseFS is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, version 2 (only).
9  *
10  * MooseFS is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with MooseFS; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA
18  * or visit http://www.gnu.org/licenses/gpl-2.0.html
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include <stdio.h>
26 #include <stddef.h>
27 #include <time.h>
28 #include <sys/types.h>
29 #include <sys/time.h>
30 #include <sys/uio.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <syslog.h>
36 #include <errno.h>
37 #include <inttypes.h>
38 #include <netinet/in.h>
39 #include <sys/resource.h>
40 #ifdef HAVE_WRITEV
41 #include <sys/uio.h>
42 #endif
43 
44 #include "MFSCommunication.h"
45 
46 #include "datapack.h"
47 #include "matoclserv.h"
48 #include "matocsserv.h"
49 #include "matomlserv.h"
50 #include "sessions.h"
51 #include "csdb.h"
52 #include "chunks.h"
53 #include "filesystem.h"
54 #include "openfiles.h"
55 #include "flocklocks.h"
56 #include "posixlocks.h"
57 #include "metadata.h"
58 #include "random.h"
59 #include "exports.h"
60 #include "datacachemgr.h"
61 #include "charts.h"
62 #include "chartsdata.h"
63 #include "storageclass.h"
64 #include "cfg.h"
65 #include "main.h"
66 #include "sockets.h"
67 #include "slogger.h"
68 #include "massert.h"
69 #include "clocks.h"
70 #include "missinglog.h"
71 #include "mfsstrerr.h"
72 #include "iptosesid.h"
73 #include "mfsalloc.h"
74 
75 #define MaxPacketSize CLTOMA_MAXPACKETSIZE
76 
77 // matoclserventry.mode
78 enum {KILL,DATA,FINISH};
79 // chunklis.type
80 enum {FUSE_WRITE,FUSE_READ,FUSE_TRUNCATE,FUSE_CREATE};
81 
82 struct matoclserventry;
83 
84 typedef struct out_packetstruct {
85 	struct out_packetstruct *next;
86 	uint8_t *startptr;
87 	uint32_t bytesleft;
88 	uint8_t data[1];
89 } out_packetstruct;
90 
91 typedef struct in_packetstruct {
92 	struct in_packetstruct *next;
93 	uint32_t type,leng;
94 	uint8_t data[1];
95 } in_packetstruct;
96 
97 typedef struct matoclserventry {
98 	uint8_t registered;
99 	uint8_t mode;				//0 - not active, 1 - read header, 2 - read packet
100 	int sock;				//socket number
101 	int32_t pdescpos;
102 	double lastread,lastwrite;		//time of last activity
103 	uint8_t input_hdr[8];
104 	uint8_t *input_startptr;
105 	uint32_t input_bytesleft;
106 	uint8_t input_end;
107 	uint8_t asize;
108 	in_packetstruct *input_packet;
109 	in_packetstruct *inputhead,**inputtail;
110 	out_packetstruct *outputhead,**outputtail;
111 	uint32_t version;
112 	uint32_t peerip;
113 
114 	uint8_t passwordrnd[32];
115 
116 	// extra data used for change session parameters after "reload"
117 	uint8_t *path;
118 	uint8_t *info;
119 	uint32_t ileng;
120 	uint8_t usepassword;
121 	uint8_t passwordmd5[16];
122 
123 	void *sesdata;
124 
125 	struct matoclserventry *next;
126 } matoclserventry;
127 
128 //static session *sessionshead=NULL;
129 static matoclserventry *matoclservhead=NULL;
130 static int lsock;
131 static int32_t lsockpdescpos;
132 
133 #define CHUNKHASHSIZE 256
134 #define CHUNKHASH(chunkid) ((chunkid)&0xFF)
135 
136 #define CHUNK_WAIT_TIMEOUT 30.0
137 
138 // status waiting chunks
139 typedef struct _swchunks {
140 	uint64_t chunkid;
141 	uint64_t prevchunkid;
142 	matoclserventry *eptr;
143 	uint64_t fleng;
144 	uint32_t msgid;
145 	uint32_t inode;
146 	uint32_t indx;
147 	uint32_t uid;
148 	uint32_t gid;
149 	uint32_t auid;
150 	uint32_t agid;
151 	uint8_t flags;
152 	uint8_t type;
153 	struct _swchunks *next;
154 } swchunks;
155 
156 // lock/busy waiting chunks
157 typedef struct _lwchunks {
158 	uint64_t chunkid;
159 	uint64_t fleng;	// TRUNCATE
160 	matoclserventry *eptr;
161 	double time;
162 	uint32_t msgid;
163 	uint32_t inode;
164 	uint32_t indx; // WRITE,READ
165 	uint32_t uid; // TRUNCATE
166 	uint32_t gids; // TRUNCATE
167 	uint32_t *gid; // TRUNCATE
168 	uint32_t auid; // TRUNCATE
169 	uint32_t agid; // TRUNCATE
170 	uint8_t chunkopflags; // WRITE,READ
171 	uint8_t flags; // TRUNCATE
172 	uint8_t type;
173 	uint8_t status;
174 	struct _lwchunks *next;
175 } lwchunks;
176 
177 static lwchunks* lwchunkshashhead[CHUNKHASHSIZE];
178 static lwchunks** lwchunkshashtail[CHUNKHASHSIZE];
179 static swchunks* swchunkshash[CHUNKHASHSIZE];
180 
181 
182 // from config
183 static char *ListenHost;
184 static char *ListenPort;
185 static uint8_t CreateFirstChunk;
186 
187 static uint32_t stats_prcvd = 0;
188 static uint32_t stats_psent = 0;
189 static uint64_t stats_brcvd = 0;
190 static uint64_t stats_bsent = 0;
191 
matoclserv_stats(uint64_t stats[5])192 void matoclserv_stats(uint64_t stats[5]) {
193 	stats[0] = stats_prcvd;
194 	stats[1] = stats_psent;
195 	stats[2] = stats_brcvd;
196 	stats[3] = stats_bsent;
197 	stats_prcvd = 0;
198 	stats_psent = 0;
199 	stats_brcvd = 0;
200 	stats_bsent = 0;
201 }
202 
matoclserv_createpacket(matoclserventry * eptr,uint32_t type,uint32_t size)203 uint8_t* matoclserv_createpacket(matoclserventry *eptr,uint32_t type,uint32_t size) {
204 	out_packetstruct *outpacket;
205 	uint8_t *ptr;
206 	uint32_t psize;
207 
208 	psize = size+8;
209 	outpacket = malloc(offsetof(out_packetstruct,data)+psize);
210 #ifndef __clang_analyzer__
211 	passert(outpacket);
212 	// clang analyzer has problem with testing for (void*)(-1) which is needed for memory allocated by mmap
213 #endif
214 	outpacket->bytesleft = psize;
215 	ptr = outpacket->data;
216 	put32bit(&ptr,type);
217 	put32bit(&ptr,size);
218 	outpacket->startptr = outpacket->data;
219 	outpacket->next = NULL;
220 	*(eptr->outputtail) = outpacket;
221 	eptr->outputtail = &(outpacket->next);
222 	return ptr;
223 }
224 
225 void matoclserv_fuse_chunk_has_changed(matoclserventry *eptr,uint32_t inode,uint32_t chindx,uint64_t chunkid,uint32_t version,uint64_t fleng,uint8_t truncateflag);
226 
227 void matoclserv_fuse_fleng_has_changed(matoclserventry *eptr,uint32_t inode,uint64_t fleng);
228 
matoclserv_fuse_write_chunk_common(matoclserventry * eptr,uint32_t msgid,uint32_t inode,uint32_t indx,uint8_t chunkopflags)229 static inline int matoclserv_fuse_write_chunk_common(matoclserventry *eptr,uint32_t msgid,uint32_t inode,uint32_t indx,uint8_t chunkopflags) {
230 	uint8_t *ptr;
231 	uint8_t status;
232 	uint64_t fleng;
233 	uint64_t prevchunkid;
234 	uint64_t chunkid;
235 	uint8_t opflag;
236 	swchunks *swc;
237 	lwchunks *lwc;
238 	uint32_t i;
239 	uint32_t version;
240 	uint8_t count;
241 	uint8_t cs_data[100*14];
242 
243 	if (sessions_get_disables(eptr->sesdata)&DISABLE_WRITE) {
244 		status = MFS_ERROR_EPERM;
245 	} else if (sessions_get_sesflags(eptr->sesdata)&SESFLAG_READONLY) {
246 		if (eptr->version>=VERSION2INT(3,0,101)) {
247 			status = MFS_ERROR_EROFS;
248 		} else {
249 			status = MFS_ERROR_IO;
250 		}
251 	} else {
252 		status = fs_writechunk(inode,indx,chunkopflags,&prevchunkid,&chunkid,&fleng,&opflag,eptr->peerip);
253 	}
254 	if (status!=MFS_STATUS_OK) {
255 		if (status==MFS_ERROR_LOCKED || status==MFS_ERROR_CHUNKBUSY) {
256 			i = CHUNKHASH(prevchunkid);
257 			lwc = malloc(sizeof(lwchunks));
258 			passert(lwc);
259 			lwc->chunkid = prevchunkid;
260 			lwc->eptr = eptr;
261 			lwc->time = monotonic_seconds();
262 			lwc->msgid = msgid;
263 			lwc->inode = inode;
264 			lwc->indx = indx;
265 			lwc->chunkopflags = chunkopflags;
266 			lwc->type = FUSE_WRITE;
267 			lwc->status = status;
268 			lwc->next = NULL;
269 			*(lwchunkshashtail[i]) = lwc;
270 			lwchunkshashtail[i] = &(lwc->next);
271 			return 1;
272 		}
273 		if (status==MFS_ERROR_EAGAIN && eptr->version<VERSION2INT(3,0,8)) {
274 			status = MFS_ERROR_LOCKED;
275 		}
276 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_WRITE_CHUNK,5);
277 		put32bit(&ptr,msgid);
278 		put8bit(&ptr,status);
279 		return 0;
280 	} else {
281 		sessions_inc_stats(eptr->sesdata,15);
282 	}
283 	if (opflag) {	// wait for operation end
284 		i = CHUNKHASH(chunkid);
285 		swc = malloc(sizeof(swchunks));
286 		passert(swc);
287 		swc->eptr = eptr;
288 		swc->inode = inode;
289 		swc->indx = indx;
290 		swc->prevchunkid = prevchunkid;
291 		swc->chunkid = chunkid;
292 		swc->msgid = msgid;
293 		swc->fleng = fleng;
294 		swc->type = FUSE_WRITE;
295 		swc->next = swchunkshash[i];
296 		swchunkshash[i] = swc;
297 	} else {	// return status immediately
298 		dcm_modify(inode,sessions_get_id(eptr->sesdata));
299 		if (eptr->version>=VERSION2INT(3,0,10)) {
300 			status = chunk_get_version_and_csdata(2,chunkid,eptr->peerip,&version,&count,cs_data);
301 		} else if (eptr->version>=VERSION2INT(1,7,32)) {
302 			status = chunk_get_version_and_csdata(1,chunkid,eptr->peerip,&version,&count,cs_data);
303 		} else {
304 			status = chunk_get_version_and_csdata(0,chunkid,eptr->peerip,&version,&count,cs_data);
305 		}
306 		if (status!=MFS_STATUS_OK) {
307 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_WRITE_CHUNK,5);
308 			put32bit(&ptr,msgid);
309 			put8bit(&ptr,status);
310 			fs_writeend(0,0,chunkid,0,NULL);	// ignore status - just do it.
311 			return 0;
312 		}
313 		if (eptr->version>=VERSION2INT(3,0,10)) {
314 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_WRITE_CHUNK,25+count*14);
315 		} else if (eptr->version>=VERSION2INT(1,7,32)) {
316 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_WRITE_CHUNK,25+count*10);
317 		} else {
318 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_WRITE_CHUNK,24+count*6);
319 		}
320 		put32bit(&ptr,msgid);
321 		if (eptr->version>=VERSION2INT(3,0,10)) {
322 			put8bit(&ptr,2);
323 		} else if (eptr->version>=VERSION2INT(1,7,32)) {
324 			put8bit(&ptr,1);
325 		}
326 		put64bit(&ptr,fleng);
327 		put64bit(&ptr,chunkid);
328 		put32bit(&ptr,version);
329 		if (count>0) {
330 			if (eptr->version>=VERSION2INT(3,0,10)) {
331 				memcpy(ptr,cs_data,count*14);
332 			} else if (eptr->version>=VERSION2INT(1,7,32)) {
333 				memcpy(ptr,cs_data,count*10);
334 			} else {
335 				memcpy(ptr,cs_data,count*6);
336 			}
337 		}
338 		matoclserv_fuse_chunk_has_changed(eptr,inode,indx,chunkid,version,fleng,0);
339 	}
340 	return 0;
341 }
342 
matoclserv_fuse_read_chunk_common(matoclserventry * eptr,uint32_t msgid,uint32_t inode,uint32_t indx,uint8_t chunkopflags)343 static inline int matoclserv_fuse_read_chunk_common(matoclserventry *eptr,uint32_t msgid,uint32_t inode,uint32_t indx,uint8_t chunkopflags) {
344 	uint8_t *ptr;
345 	uint8_t status;
346 	uint64_t chunkid;
347 	uint64_t fleng;
348 	uint32_t version;
349 	lwchunks *lwc;
350 	uint32_t i;
351 	uint8_t count;
352 	uint8_t cs_data[100*14];
353 
354 	if (sessions_get_disables(eptr->sesdata)&DISABLE_READ) {
355 		status = MFS_ERROR_EPERM;
356 	} else {
357 		status = fs_readchunk(inode,indx,chunkopflags,&chunkid,&fleng);
358 	}
359 	if (status!=MFS_STATUS_OK) {
360 		if (status==MFS_ERROR_LOCKED || status==MFS_ERROR_CHUNKBUSY) {
361 			i = CHUNKHASH(chunkid);
362 			lwc = malloc(sizeof(lwchunks));
363 			passert(lwc);
364 			lwc->chunkid = chunkid;
365 			lwc->eptr = eptr;
366 			lwc->time = monotonic_seconds();
367 			lwc->msgid = msgid;
368 			lwc->inode = inode;
369 			lwc->indx = indx;
370 			lwc->chunkopflags = chunkopflags;
371 			lwc->type = FUSE_READ;
372 			lwc->status = status;
373 			lwc->next = NULL;
374 			*(lwchunkshashtail[i]) = lwc;
375 			lwchunkshashtail[i] = &(lwc->next);
376 			return 1;
377 		}
378 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_READ_CHUNK,5);
379 		put32bit(&ptr,msgid);
380 		put8bit(&ptr,status);
381 		return 0;
382 	} else {
383 		sessions_inc_stats(eptr->sesdata,14);
384 		if (chunkid>0) {
385 			if (eptr->version>=VERSION2INT(3,0,10)) {
386 				status = chunk_get_version_and_csdata(2,chunkid,eptr->peerip,&version,&count,cs_data);
387 			} else if (eptr->version>=VERSION2INT(1,7,32)) {
388 				status = chunk_get_version_and_csdata(1,chunkid,eptr->peerip,&version,&count,cs_data);
389 			} else {
390 				status = chunk_get_version_and_csdata(0,chunkid,eptr->peerip,&version,&count,cs_data);
391 			}
392 		} else {
393 			version = 0;
394 			count = 0;
395 		}
396 	}
397 	if (status!=MFS_STATUS_OK) {
398 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_READ_CHUNK,5);
399 		put32bit(&ptr,msgid);
400 		put8bit(&ptr,status);
401 		return 0;
402 	}
403 	dcm_access(inode,sessions_get_id(eptr->sesdata));
404 	if (eptr->version>=VERSION2INT(3,0,10)) {
405 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_READ_CHUNK,25+count*14);
406 	} else if (eptr->version>=VERSION2INT(1,7,32)) {
407 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_READ_CHUNK,25+count*10);
408 	} else {
409 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_READ_CHUNK,24+count*6);
410 	}
411 	put32bit(&ptr,msgid);
412 	if (eptr->version>=VERSION2INT(3,0,10)) {
413 		put8bit(&ptr,2);
414 	} else if (eptr->version>=VERSION2INT(1,7,32)) {
415 		put8bit(&ptr,1);
416 	}
417 	put64bit(&ptr,fleng);
418 	put64bit(&ptr,chunkid);
419 	put32bit(&ptr,version);
420 	if (count>0) {
421 		if (eptr->version>=VERSION2INT(3,0,10)) {
422 			memcpy(ptr,cs_data,count*14);
423 		} else if (eptr->version>=VERSION2INT(1,7,32)) {
424 			memcpy(ptr,cs_data,count*10);
425 		} else {
426 			memcpy(ptr,cs_data,count*6);
427 		}
428 	}
429 	return 0;
430 }
431 
matoclserv_fuse_truncate_common(matoclserventry * eptr,uint32_t msgid,uint32_t inode,uint8_t flags,uint32_t uid,uint32_t gids,uint32_t * gid,uint32_t auid,uint32_t agid,uint64_t fleng)432 static inline int matoclserv_fuse_truncate_common(matoclserventry *eptr,uint32_t msgid,uint32_t inode,uint8_t flags,uint32_t uid,uint32_t gids,uint32_t *gid,uint32_t auid,uint32_t agid,uint64_t fleng) {
433 	uint32_t indx;
434 	uint32_t i;
435 	uint8_t attr[ATTR_RECORD_SIZE];
436 	uint8_t *ptr;
437 	uint8_t status;
438 	uint64_t prevlength;
439 	uint64_t prevchunkid;
440 	uint32_t disables;
441 	swchunks *swc;
442 	lwchunks *lwc;
443 	uint64_t chunkid;
444 //	uint8_t locked;
445 
446 	status = MFS_STATUS_OK;
447 	disables = sessions_get_disables(eptr->sesdata);
448 	if (flags & (TRUNCATE_FLAG_RESERVE|TRUNCATE_FLAG_UPDATE)) { // part of write - not actual truncate
449 		if (disables&DISABLE_WRITE) {
450 			status = MFS_ERROR_EPERM;
451 		}
452 	} else {
453 		if ((disables&(DISABLE_TRUNCATE|DISABLE_SETLENGTH))==(DISABLE_TRUNCATE|DISABLE_SETLENGTH)) {
454 			status = MFS_ERROR_EPERM;
455 		}
456 	}
457 	if (status==MFS_STATUS_OK) {
458 		status = fs_try_setlength(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,flags,uid,gids,gid,((disables&DISABLE_TRUNCATE)?1:0)|((disables&DISABLE_SETLENGTH)?2:0),fleng,&indx,&prevchunkid,&chunkid);
459 	}
460 	if (status==MFS_ERROR_DELAYED) {
461 		i = CHUNKHASH(chunkid);
462 		swc = malloc(sizeof(swchunks));
463 		passert(swc);
464 		swc->chunkid = chunkid;
465 		swc->prevchunkid = prevchunkid;
466 		swc->eptr = eptr;
467 		swc->msgid = msgid;
468 		swc->inode = inode;
469 		swc->indx = indx;
470 		swc->uid = uid;
471 		swc->gid = gid[0];
472 		swc->auid = auid;
473 		swc->agid = agid;
474 		swc->fleng = fleng;
475 		swc->flags = flags;
476 		swc->type = FUSE_TRUNCATE;
477 		swc->next = swchunkshash[i];
478 		swchunkshash[i] = swc;
479 		sessions_inc_stats(eptr->sesdata,2);
480 		return 0;
481 	}
482 	if (status==MFS_ERROR_LOCKED || status==MFS_ERROR_CHUNKBUSY) {
483 //		locked = 1;
484 		i = CHUNKHASH(prevchunkid);
485 		lwc = malloc(sizeof(lwchunks)+sizeof(uint32_t)*gids);
486 		passert(lwc);
487 		lwc->chunkid = prevchunkid;
488 		lwc->fleng = fleng;
489 		lwc->eptr = eptr;
490 		lwc->status = status;
491 		lwc->time = monotonic_seconds();
492 		lwc->msgid = msgid;
493 		lwc->inode = inode;
494 		lwc->indx = indx;
495 		lwc->uid = uid;
496 		lwc->gids = gids;
497 		lwc->gid = (uint32_t*)(((uint8_t*)lwc)+sizeof(lwchunks));
498 		memcpy(lwc->gid,gid,sizeof(uint32_t)*gids);
499 		lwc->auid = auid;
500 		lwc->agid = agid;
501 		lwc->flags = flags;
502 		lwc->type = FUSE_TRUNCATE;
503 		lwc->status = status;
504 		lwc->next = NULL;
505 		*(lwchunkshashtail[i]) = lwc;
506 		lwchunkshashtail[i] = &(lwc->next);
507 		return 1;
508 //	} else {
509 //		locked = 0;
510 	}
511 	if (status==MFS_STATUS_OK) {
512 		status = fs_do_setlength(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,flags,uid,gid[0],auid,agid,fleng,attr,&prevlength);
513 	}
514 	if (status==MFS_STATUS_OK && (flags & TRUNCATE_FLAG_UPDATE)==0) {
515 		dcm_modify(inode,sessions_get_id(eptr->sesdata));
516 	}
517 	if (status!=MFS_STATUS_OK) {
518 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_TRUNCATE,5);
519 		put32bit(&ptr,msgid);
520 		put8bit(&ptr,status);
521 	} else {
522 		if (eptr->version>=VERSION2INT(3,0,113)) {
523 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_TRUNCATE,(eptr->asize+12));
524 		} else {
525 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_TRUNCATE,(eptr->asize+4));
526 		}
527 		put32bit(&ptr,msgid);
528 		if (eptr->version>=VERSION2INT(3,0,113)) {
529 			put64bit(&ptr,prevlength);
530 		}
531 		memcpy(ptr,attr,eptr->asize);
532 		if (flags & TRUNCATE_FLAG_RESERVE) {
533 			fleng += prevlength;
534 		}
535 		matoclserv_fuse_fleng_has_changed(eptr,inode,fleng);
536 	}
537 	sessions_inc_stats(eptr->sesdata,2);
538 	return 0;
539 }
540 
matoclserv_chunk_unlocked(uint64_t chunkid,void * cptr)541 void matoclserv_chunk_unlocked(uint64_t chunkid,void *cptr) {
542 	lwchunks *lwc,**plwc;
543 	uint8_t locked;
544 
545 	plwc = lwchunkshashhead + CHUNKHASH(chunkid);
546 	while ((lwc = *plwc)) {
547 		if (lwc->chunkid == chunkid && lwc->eptr->mode==DATA) {
548 			if (lwc->type == FUSE_TRUNCATE) {
549 				locked = matoclserv_fuse_truncate_common(lwc->eptr,lwc->msgid,lwc->inode,lwc->flags,lwc->uid,lwc->gids,lwc->gid,lwc->auid,lwc->agid,lwc->fleng);
550 			} else if (lwc->type == FUSE_WRITE) {
551 				locked = matoclserv_fuse_write_chunk_common(lwc->eptr,lwc->msgid,lwc->inode,lwc->indx,lwc->chunkopflags);
552 			} else if (lwc->type == FUSE_READ) {
553 				locked = matoclserv_fuse_read_chunk_common(lwc->eptr,lwc->msgid,lwc->inode,lwc->indx,lwc->chunkopflags);
554 			} else {
555 				locked = 0;
556 			}
557 			*plwc = lwc->next;
558 			free(lwc);
559 			if (locked || chunk_locked_or_busy(cptr)) {
560 				break;
561 			}
562 		} else {
563 			plwc = &(lwc->next);
564 		}
565 	}
566 	if (*plwc==NULL) {
567 		lwchunkshashtail[CHUNKHASH(chunkid)] = plwc;
568 	}
569 }
570 
matoclserv_timeout_waiting_ops(void)571 void matoclserv_timeout_waiting_ops(void) {
572 	lwchunks *lwc,**plwc;
573 	uint8_t *ptr;
574 	uint32_t i;
575 	double curtime;
576 
577 	curtime = monotonic_seconds();
578 	for (i=0 ; i<CHUNKHASHSIZE ; i++) {
579 		plwc = lwchunkshashhead + i;
580 		while ((lwc = *plwc)) {
581 			if (lwc->time + CHUNK_WAIT_TIMEOUT < curtime) {
582 				if (lwc->type == FUSE_TRUNCATE) {
583 					ptr = matoclserv_createpacket(lwc->eptr,MATOCL_FUSE_TRUNCATE,5);
584 					put32bit(&ptr,lwc->msgid);
585 					put8bit(&ptr,lwc->status);
586 				} else if (lwc->type == FUSE_WRITE) {
587 					ptr = matoclserv_createpacket(lwc->eptr,MATOCL_FUSE_WRITE_CHUNK,5);
588 					put32bit(&ptr,lwc->msgid);
589 					put8bit(&ptr,lwc->status);
590 				} else if (lwc->type == FUSE_READ) {
591 					ptr = matoclserv_createpacket(lwc->eptr,MATOCL_FUSE_READ_CHUNK,5);
592 					put32bit(&ptr,lwc->msgid);
593 					put8bit(&ptr,lwc->status);
594 				}
595 				*plwc = lwc->next;
596 				free(lwc);
597 			} else {
598 				plwc = &(lwc->next);
599 			}
600 		}
601 		lwchunkshashtail[i] = plwc;
602 	}
603 }
604 
matoclserv_chunk_status(uint64_t chunkid,uint8_t status)605 void matoclserv_chunk_status(uint64_t chunkid,uint8_t status) {
606 	uint32_t msgid,inode,indx,uid,gid,auid,agid;
607 	uint64_t fleng,prevchunkid,prevlength;
608 	uint8_t flags,type,attr[ATTR_RECORD_SIZE];
609 	uint32_t version;
610 	uint8_t *ptr;
611 	uint8_t count;
612 	uint8_t cs_data[100*14];
613 	matoclserventry *eptr;
614 	swchunks *swc,**pswc;
615 
616 	eptr = NULL;
617 	prevchunkid = 0;
618 	msgid = 0;
619 	fleng = 0;
620 	type = 0;
621 	inode = 0;
622 	indx = 0;
623 	uid = 0;
624 	gid = 0;
625 	auid = 0;
626 	agid = 0;
627 	flags = 0;
628 	pswc = swchunkshash + CHUNKHASH(chunkid);
629 	while ((swc = *pswc)) {
630 		if (swc->chunkid == chunkid) {
631 			eptr = swc->eptr;
632 			prevchunkid = swc->prevchunkid;
633 			msgid = swc->msgid;
634 			fleng = swc->fleng;
635 			type = swc->type;
636 			flags = swc->flags;
637 			inode = swc->inode;
638 			indx = swc->indx;
639 			uid = swc->uid;
640 			gid = swc->gid;
641 			auid = swc->auid;
642 			agid = swc->agid;
643 			*pswc = swc->next;
644 			free(swc);
645 			break;
646 		} else {
647 			pswc = &(swc->next);
648 		}
649 	}
650 
651 	if (!eptr) {
652 //		syslog(LOG_WARNING,"got chunk status, but don't want it");
653 		return;
654 	}
655 	if (eptr->mode!=DATA) {
656 		return;
657 	}
658 	if (status==MFS_STATUS_OK && type!=FUSE_CREATE) {
659 		dcm_modify(inode,sessions_get_id(eptr->sesdata));
660 	}
661 	switch (type) {
662 	case FUSE_CREATE:
663 		if (status==MFS_STATUS_OK) { // just unlock this chunk
664 			fs_writeend(inode,0,chunkid,0,NULL);
665 		}
666 		return;
667 	case FUSE_WRITE:
668 		if (status==MFS_STATUS_OK) {
669 			if (eptr->version>=VERSION2INT(3,0,10)) {
670 				status = chunk_get_version_and_csdata(2,chunkid,eptr->peerip,&version,&count,cs_data);
671 			} else if (eptr->version>=VERSION2INT(1,7,32)) {
672 				status = chunk_get_version_and_csdata(1,chunkid,eptr->peerip,&version,&count,cs_data);
673 			} else {
674 				status = chunk_get_version_and_csdata(0,chunkid,eptr->peerip,&version,&count,cs_data);
675 			}
676 			//syslog(LOG_NOTICE,"get version for chunk %"PRIu64" -> %"PRIu32,chunkid,version);
677 		}
678 		if (status!=MFS_STATUS_OK) {
679 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_WRITE_CHUNK,5);
680 			put32bit(&ptr,msgid);
681 			put8bit(&ptr,status);
682 			fs_rollback(inode,indx,prevchunkid,chunkid);	// ignore status - it's error anyway
683 			return;
684 		}
685 		if (eptr->version>=VERSION2INT(3,0,10)) {
686 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_WRITE_CHUNK,25+count*14);
687 		} else if (eptr->version>=VERSION2INT(1,7,32)) {
688 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_WRITE_CHUNK,25+count*10);
689 		} else {
690 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_WRITE_CHUNK,24+count*6);
691 		}
692 		put32bit(&ptr,msgid);
693 		if (eptr->version>=VERSION2INT(3,0,10)) {
694 			put8bit(&ptr,2);
695 		} else if (eptr->version>=VERSION2INT(1,7,32)) {
696 			put8bit(&ptr,1);
697 		}
698 		put64bit(&ptr,fleng);
699 		put64bit(&ptr,chunkid);
700 		put32bit(&ptr,version);
701 		if (count>0) {
702 			if (eptr->version>=VERSION2INT(3,0,10)) {
703 				memcpy(ptr,cs_data,count*14);
704 			} else if (eptr->version>=VERSION2INT(1,7,32)) {
705 				memcpy(ptr,cs_data,count*10);
706 			} else {
707 				memcpy(ptr,cs_data,count*6);
708 			}
709 		}
710 		matoclserv_fuse_chunk_has_changed(eptr,inode,indx,chunkid,version,fleng,0);
711 //		for (i=0 ; i<count ; i++) {
712 //			if (matocsserv_getlocation(sptr[i],&ip,&port)<0) {
713 //				put32bit(&ptr,0);
714 //				put16bit(&ptr,0);
715 //			} else {
716 //				put32bit(&ptr,ip);
717 //				put16bit(&ptr,port);
718 //			}
719 //		}
720 		return;
721 	case FUSE_TRUNCATE:
722 		if (status!=MFS_STATUS_OK) {
723 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_TRUNCATE,5);
724 			put32bit(&ptr,msgid);
725 			put8bit(&ptr,status);
726 			fs_rollback(inode,indx,prevchunkid,chunkid);	// ignore status - it's error anyway
727 			return;
728 		}
729 		fs_end_setlength(chunkid); // chunk unlock
730 		status = fs_do_setlength(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,flags,uid,gid,auid,agid,fleng,attr,&prevlength);
731 		if (status!=MFS_STATUS_OK) {
732 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_TRUNCATE,5);
733 			put32bit(&ptr,msgid);
734 			put8bit(&ptr,status);
735 			return;
736 		}
737 		if (eptr->version>=VERSION2INT(3,0,113)) {
738 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_TRUNCATE,eptr->asize+12);
739 		} else {
740 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_TRUNCATE,eptr->asize+4);
741 		}
742 		put32bit(&ptr,msgid);
743 		if (eptr->version>=VERSION2INT(3,0,113)) {
744 			put64bit(&ptr,prevlength);
745 		}
746 		memcpy(ptr,attr,eptr->asize);
747 		chunk_get_version(chunkid,&version);
748 		if (flags & TRUNCATE_FLAG_RESERVE) {
749 			fleng += prevlength;
750 		}
751 		matoclserv_fuse_chunk_has_changed(eptr,inode,indx,chunkid,version,fleng,1);
752 		return;
753 	default:
754 		syslog(LOG_WARNING,"got chunk status, but operation type is unknown");
755 	}
756 }
757 
matoclserv_cserv_list(matoclserventry * eptr,const uint8_t * data,uint32_t length)758 void matoclserv_cserv_list(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
759 	uint8_t *ptr;
760 	(void)data;
761 	if (length!=0) {
762 		syslog(LOG_NOTICE,"CLTOMA_CSERV_LIST - wrong size (%"PRIu32"/0)",length);
763 		eptr->mode = KILL;
764 		return;
765 	}
766 	ptr = matoclserv_createpacket(eptr,MATOCL_CSERV_LIST,csdb_servlist_size());
767 	csdb_servlist_data(ptr);
768 }
769 
matoclserv_cserv_command(matoclserventry * eptr,const uint8_t * data,uint32_t length)770 void matoclserv_cserv_command(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
771 	uint32_t ip;
772 	uint16_t port;
773 	uint8_t cmd,status;
774 	uint8_t *ptr;
775 	if (length!=6 && length!=7) {
776 		syslog(LOG_NOTICE,"CLTOMA_CSSERV_COMMAND - wrong size (%"PRIu32"/6|7)",length);
777 		eptr->mode = KILL;
778 		return;
779 	}
780 	if (length==7) {
781 		cmd = get8bit(&data);
782 	} else {
783 		cmd = MFS_CSSERV_COMMAND_REMOVE;
784 	}
785 	ip = get32bit(&data);
786 	port = get16bit(&data);
787 	status = MFS_ERROR_EINVAL;
788 	if (cmd==MFS_CSSERV_COMMAND_REMOVE) {
789 		status = csdb_remove_server(ip,port);
790 	} else if (cmd==MFS_CSSERV_COMMAND_BACKTOWORK) {
791 		status = csdb_back_to_work(ip,port);
792 	} else if (cmd==MFS_CSSERV_COMMAND_MAINTENANCEON) {
793 		status = csdb_maintenance(ip,port,1);
794 	} else if (cmd==MFS_CSSERV_COMMAND_MAINTENANCEOFF) {
795 		status = csdb_maintenance(ip,port,0);
796 	}
797 	if (length==6) {
798 		matoclserv_createpacket(eptr,MATOCL_CSSERV_COMMAND,0);
799 	} else {
800 		ptr = matoclserv_createpacket(eptr,MATOCL_CSSERV_COMMAND,1);
801 		put8bit(&ptr,status);
802 	}
803 }
804 
matoclserv_session_list(matoclserventry * eptr,const uint8_t * data,uint32_t length)805 void matoclserv_session_list(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
806 	uint8_t *ptr;
807 	uint32_t size;
808 	uint8_t vmode;
809 	(void)data;
810 	if (length!=0 && length!=1) {
811 		syslog(LOG_NOTICE,"CLTOMA_SESSION_LIST - wrong size (%"PRIu32"/0)",length);
812 		eptr->mode = KILL;
813 		return;
814 	}
815 	if (length==0) {
816 		vmode = 0;
817 	} else {
818 		vmode = get8bit(&data);
819 	}
820 	size = sessions_datasize(vmode);
821 	ptr = matoclserv_createpacket(eptr,MATOCL_SESSION_LIST,size);
822 	sessions_datafill(ptr,vmode);
823 }
824 
matoclserv_session_command(matoclserventry * eptr,const uint8_t * data,uint32_t length)825 void matoclserv_session_command(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
826 	uint32_t sessionid;
827 	uint8_t cmd,status;
828 	uint8_t *ptr;
829 	if (length!=5) {
830 		syslog(LOG_NOTICE,"CLTOMA_SESSION_COMMAND - wrong size (%"PRIu32"/5)",length);
831 		eptr->mode = KILL;
832 		return;
833 	}
834 	cmd = get8bit(&data);
835 	sessionid = get32bit(&data);
836 	if (cmd==MFS_SESSION_COMMAND_REMOVE) {
837 		status = sessions_force_remove(sessionid);
838 	} else {
839 		status = MFS_ERROR_EINVAL;
840 	}
841 	ptr = matoclserv_createpacket(eptr,MATOCL_SESSION_COMMAND,1);
842 	put8bit(&ptr,status);
843 }
844 
matoclserv_chart(matoclserventry * eptr,const uint8_t * data,uint32_t length)845 void matoclserv_chart(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
846 	uint32_t chartid;
847 	uint8_t *ptr;
848 	uint32_t l;
849 	uint16_t w,h;
850 
851 	if (length!=4 && length!=8) {
852 		syslog(LOG_NOTICE,"CLTOAN_CHART - wrong size (%"PRIu32"/4|8)",length);
853 		eptr->mode = KILL;
854 		return;
855 	}
856 	chartid = get32bit(&data);
857 	if (length==8) {
858 		w = get16bit(&data);
859 		h = get16bit(&data);
860 	} else {
861 		w = 0;
862 		h = 0;
863 	}
864 	l = charts_make_png(chartid,w,h);
865 	ptr = matoclserv_createpacket(eptr,ANTOCL_CHART,l);
866 	if (l>0) {
867 		charts_get_png(ptr);
868 	}
869 }
870 
matoclserv_chart_data(matoclserventry * eptr,const uint8_t * data,uint32_t length)871 void matoclserv_chart_data(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
872 	uint32_t chartid;
873 	uint32_t maxentries;
874 	uint8_t *ptr;
875 	uint32_t l;
876 
877 	if (length!=4 && length!=8) {
878 		syslog(LOG_NOTICE,"CLTOAN_CHART_DATA - wrong size (%"PRIu32"/4|8)",length);
879 		eptr->mode = KILL;
880 		return;
881 	}
882 	chartid = get32bit(&data);
883 	if (length==8) {
884 		maxentries = get32bit(&data);
885 	} else {
886 		maxentries = UINT32_C(0xFFFFFFFF);
887 	}
888 	l = charts_makedata(NULL,chartid,maxentries);
889 	ptr = matoclserv_createpacket(eptr,ANTOCL_CHART_DATA,l);
890 	if (l>0) {
891 		charts_makedata(ptr,chartid,maxentries);
892 	}
893 }
894 
matoclserv_monotonic_data(matoclserventry * eptr,const uint8_t * data,uint32_t length)895 void matoclserv_monotonic_data(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
896 	uint8_t *ptr;
897 	uint32_t l;
898 
899 	(void)data;
900 	if (length!=0) {
901 		syslog(LOG_NOTICE,"CLTOAN_MONOTONIC_DATA - wrong size (%"PRIu32"/0)",length);
902 		eptr->mode = KILL;
903 		return;
904 	}
905 	l = charts_monotonic_data(NULL);
906 	ptr = matoclserv_createpacket(eptr,ANTOCL_MONOTONIC_DATA,l);
907 	if (l>0) {
908 		charts_monotonic_data(ptr);
909 	}
910 }
911 
matoclserv_get_version(matoclserventry * eptr,const uint8_t * data,uint32_t length)912 void matoclserv_get_version(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
913 	uint32_t msgid = 0;
914 	uint8_t *ptr;
915 	static const char vstring[] = VERSSTR;
916 	if (length!=0 && length!=4) {
917 		syslog(LOG_NOTICE,"ANTOAN_GET_VERSION - wrong size (%"PRIu32"/4|0)",length);
918 		eptr->mode = KILL;
919 		return;
920 	}
921 	if (length==4) {
922 		msgid = get32bit(&data);
923 		ptr = matoclserv_createpacket(eptr,ANTOAN_VERSION,4+4+strlen(vstring));
924 		put32bit(&ptr,msgid);
925 	} else {
926 		ptr = matoclserv_createpacket(eptr,ANTOAN_VERSION,4+strlen(vstring));
927 	}
928 	put16bit(&ptr,VERSMAJ);
929 	put8bit(&ptr,VERSMID);
930 	put8bit(&ptr,VERSMIN);
931 	memcpy(ptr,vstring,strlen(vstring));
932 }
933 
matoclserv_get_config(matoclserventry * eptr,const uint8_t * data,uint32_t length)934 void matoclserv_get_config(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
935 	uint32_t msgid;
936 	char name[256];
937 	uint8_t nleng;
938 	uint32_t vleng;
939 	char *val;
940 	uint8_t *ptr;
941 
942 	if (length<5) {
943 		syslog(LOG_NOTICE,"ANTOAN_GET_CONFIG - wrong size (%"PRIu32")",length);
944 		eptr->mode = KILL;
945 		return;
946 	}
947 	msgid = get32bit(&data);
948 	nleng = get8bit(&data);
949 	if (length!=5U+(uint32_t)nleng) {
950 		syslog(LOG_NOTICE,"ANTOAN_GET_CONFIG - wrong size (%"PRIu32":nleng=%"PRIu8")",length,nleng);
951 		eptr->mode = KILL;
952 		return;
953 	}
954 	memcpy(name,data,nleng);
955 	name[nleng] = 0;
956 	val = cfg_getstr(name,"");
957 	vleng = strlen(val);
958 	if (vleng>255) {
959 		vleng=255;
960 	}
961 	ptr = matoclserv_createpacket(eptr,ANTOAN_CONFIG_VALUE,5+vleng);
962 	put32bit(&ptr,msgid);
963 	put8bit(&ptr,vleng);
964 	memcpy(ptr,val,vleng);
965 }
966 
matoclserv_module_info(matoclserventry * eptr,const uint8_t * data,uint32_t length)967 void matoclserv_module_info(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
968 	uint32_t msgid = 0;
969 	uint8_t *ptr;
970 
971 	if (length!=0 && length!=4) {
972 		syslog(LOG_NOTICE,"ANTOAN_GET_VERSION - wrong size (%"PRIu32"/4|0)",length);
973 		eptr->mode = KILL;
974 		return;
975 	}
976 	if (length==4) {
977 		msgid = get32bit(&data);
978 		ptr = matoclserv_createpacket(eptr,ANTOCL_MODULE_INFO,25);
979 		put32bit(&ptr,msgid);
980 	} else {
981 		ptr = matoclserv_createpacket(eptr,ANTOCL_MODULE_INFO,21);
982 	}
983 	put8bit(&ptr,MODULE_TYPE_MASTER);
984 	put16bit(&ptr,VERSMAJ);
985 	put8bit(&ptr,VERSMID);
986 	put8bit(&ptr,VERSMIN);
987 	put16bit(&ptr,0);
988 	put64bit(&ptr,meta_get_id());
989 	put32bit(&ptr,0);
990 	put16bit(&ptr,0);
991 }
992 
matoclserv_list_open_files(matoclserventry * eptr,const uint8_t * data,uint32_t length)993 void matoclserv_list_open_files(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
994 	uint32_t msgid = 0;
995 	uint32_t sessionid;
996 	uint32_t size;
997 	uint8_t *ptr;
998 
999 	if (length!=4 && length!=8) {
1000 		syslog(LOG_NOTICE,"CLTOMA_LIST_OPEN_FILES - wrong size (%"PRIu32"/4|8)",length);
1001 		eptr->mode = KILL;
1002 		return;
1003 	}
1004 	if (length==8) {
1005 		msgid = get32bit(&data);
1006 	}
1007 	sessionid = get32bit(&data);
1008 	size = of_lsof(sessionid,NULL);
1009 	if (length==8) {
1010 		ptr = matoclserv_createpacket(eptr,MATOCL_LIST_OPEN_FILES,4+size);
1011 		put32bit(&ptr,msgid);
1012 	} else {
1013 		ptr = matoclserv_createpacket(eptr,MATOCL_LIST_OPEN_FILES,size);
1014 	}
1015 	of_lsof(sessionid,ptr);
1016 }
1017 
matoclserv_list_acquired_locks(matoclserventry * eptr,const uint8_t * data,uint32_t length)1018 void matoclserv_list_acquired_locks(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
1019 	uint32_t msgid = 0;
1020 	uint32_t inode;
1021 	uint32_t size;
1022 	uint8_t *ptr;
1023 
1024 	if (length!=4 && length!=8) {
1025 		syslog(LOG_NOTICE,"CLTOMA_LIST_ACQUIRED_LOCKS - wrong size (%"PRIu32"/4|8)",length);
1026 		eptr->mode = KILL;
1027 		return;
1028 	}
1029 	if (length==8) {
1030 		msgid = get32bit(&data);
1031 	}
1032 	inode = get32bit(&data);
1033 	size = posix_lock_list(inode,NULL) + flock_list(inode,NULL);
1034 	if (length==8) {
1035 		ptr = matoclserv_createpacket(eptr,MATOCL_LIST_ACQUIRED_LOCKS,4+size);
1036 		put32bit(&ptr,msgid);
1037 	} else {
1038 		ptr = matoclserv_createpacket(eptr,MATOCL_LIST_ACQUIRED_LOCKS,size);
1039 	}
1040 	posix_lock_list(inode,ptr);
1041 	flock_list(inode,ptr);
1042 }
1043 
matoclserv_mass_resolve_paths(matoclserventry * eptr,const uint8_t * data,uint32_t length)1044 void matoclserv_mass_resolve_paths(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
1045 	static uint32_t *inodetab = NULL;
1046 	static uint32_t *psizetab = NULL;
1047 	static uint32_t tabsleng = 0;
1048 	uint32_t i,j;
1049 	uint32_t totalsize;
1050 	uint32_t psize;
1051 	uint8_t *ptr;
1052 
1053 	if ((length%4)!=0) {
1054 		syslog(LOG_NOTICE,"CLTOMA_MASS_RESOLVE_PATHS - wrong size (%"PRIu32"/N*4)",length);
1055 		eptr->mode = KILL;
1056 		return;
1057 	}
1058 	length>>=2;
1059 	if (length>tabsleng) {
1060 		if (inodetab) {
1061 			free(inodetab);
1062 		}
1063 		if (psizetab) {
1064 			free(psizetab);
1065 		}
1066 		tabsleng = ((length+0xFF)&0xFFFFFF00);
1067 		inodetab = malloc(sizeof(uint32_t)*tabsleng);
1068 		passert(inodetab);
1069 		psizetab = malloc(sizeof(uint32_t)*tabsleng);
1070 		passert(psizetab);
1071 	}
1072 	j = 0;
1073 	totalsize = 0;
1074 	while (length>0) {
1075 		i = get32bit(&data);
1076 		if (i>0) {
1077 			fs_get_paths_size(MFS_ROOT_ID,i,&psize);
1078 			inodetab[j] = i;
1079 			psizetab[j] = psize;
1080 			j++;
1081 			totalsize += 8 + psize;
1082 		}
1083 		length--;
1084 	}
1085 	ptr = matoclserv_createpacket(eptr,MATOCL_MASS_RESOLVE_PATHS,totalsize);
1086 	for (i=0 ; i<j ; i++) {
1087 		put32bit(&ptr,inodetab[i]);
1088 		put32bit(&ptr,psizetab[i]);
1089 		fs_get_paths_data(MFS_ROOT_ID,inodetab[i],ptr);
1090 		ptr+=psizetab[i];
1091 	}
1092 }
1093 
matoclserv_sclass_info(matoclserventry * eptr,const uint8_t * data,uint32_t length)1094 void matoclserv_sclass_info(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
1095 	uint8_t *ptr;
1096 	if (length!=0) {
1097 		syslog(LOG_NOTICE,"CLTOMA_SCLASS_INFO - wrong size (%"PRIu32"/0)",length);
1098 		eptr->mode = KILL;
1099 		return;
1100 	}
1101 	(void)data;
1102 	ptr = matoclserv_createpacket(eptr,MATOCL_SCLASS_INFO,sclass_info(NULL));
1103 	sclass_info(ptr);
1104 }
1105 
matoclserv_missing_chunks(matoclserventry * eptr,const uint8_t * data,uint32_t length)1106 void matoclserv_missing_chunks(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
1107 	uint8_t *ptr;
1108 	uint8_t mode;
1109 	if (length!=0 && length!=1) {
1110 		syslog(LOG_NOTICE,"CLTOMA_MISSING_CHUNKS - wrong size (%"PRIu32"/0|1)",length);
1111 		eptr->mode = KILL;
1112 		return;
1113 	}
1114 	if (length==1) {
1115 		mode = get8bit(&data);
1116 	} else {
1117 		mode = 0;
1118 	}
1119 	ptr = matoclserv_createpacket(eptr,MATOCL_MISSING_CHUNKS,missing_log_getdata(NULL,mode));
1120 	missing_log_getdata(ptr,mode);
1121 }
1122 
matoclserv_node_info(matoclserventry * eptr,const uint8_t * data,uint32_t length)1123 void matoclserv_node_info(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
1124 	uint8_t *ptr;
1125 	uint32_t inode;
1126 	uint32_t maxentries;
1127 	uint64_t continueid;
1128 	uint32_t msgid;
1129 
1130 	if (length!=16 && length!=20) {
1131 		syslog(LOG_NOTICE,"CLTOMA_NODE_INFO - wrong size (%"PRIu32"/16|20)",length);
1132 		eptr->mode = KILL;
1133 		return;
1134 	}
1135 	if (length==20) {
1136 		msgid = get32bit(&data);
1137 	} else {
1138 		msgid = 0;
1139 	}
1140 	inode = get32bit(&data);
1141 	maxentries = get32bit(&data);
1142 	continueid = get64bit(&data);
1143 	ptr = matoclserv_createpacket(eptr,MATOCL_NODE_INFO,fs_node_info(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,maxentries,continueid,NULL)+((length==20)?4:0));
1144 	if (length==20) {
1145 		put32bit(&ptr,msgid);
1146 	}
1147 	fs_node_info(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,maxentries,continueid,ptr);
1148 }
1149 
matoclserv_info(matoclserventry * eptr,const uint8_t * data,uint32_t length)1150 void matoclserv_info(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
1151 	uint64_t totalspace,availspace,freespace,trspace,respace;
1152 	uint64_t memusage,syscpu,usercpu;
1153 	uint32_t trnodes,renodes,inodes,dnodes,fnodes;
1154 	uint32_t chunks,chunkcopies,tdcopies;
1155 	uint32_t lsstore,lstime;
1156 	uint8_t lsstat;
1157 	uint8_t *ptr;
1158 	(void)data;
1159 	if (length!=0) {
1160 		syslog(LOG_NOTICE,"CLTOMA_INFO - wrong size (%"PRIu32"/0)",length);
1161 		eptr->mode = KILL;
1162 		return;
1163 	}
1164 	meta_info(&lsstore,&lstime,&lsstat);
1165 	fs_info(&totalspace,&availspace,&freespace,&trspace,&trnodes,&respace,&renodes,&inodes,&dnodes,&fnodes);
1166 	chunk_info(&chunks,&chunkcopies,&tdcopies);
1167 	chartsdata_resusage(&memusage,&syscpu,&usercpu);
1168 	ptr = matoclserv_createpacket(eptr,MATOCL_INFO,149);
1169 	/* put32bit(&buff,VERSION): */
1170 	put16bit(&ptr,VERSMAJ);
1171 	put8bit(&ptr,VERSMID);
1172 	put8bit(&ptr,VERSMIN);
1173 	put64bit(&ptr,memusage);
1174 	put64bit(&ptr,syscpu);
1175 	put64bit(&ptr,usercpu);
1176 	put64bit(&ptr,totalspace);
1177 	put64bit(&ptr,availspace);
1178 	put64bit(&ptr,freespace);
1179 	put64bit(&ptr,trspace);
1180 	put32bit(&ptr,trnodes);
1181 	put64bit(&ptr,respace);
1182 	put32bit(&ptr,renodes);
1183 	put32bit(&ptr,inodes);
1184 	put32bit(&ptr,dnodes);
1185 	put32bit(&ptr,fnodes);
1186 	put32bit(&ptr,chunks);
1187 	put32bit(&ptr,chunkcopies);
1188 	put32bit(&ptr,tdcopies);
1189 	put32bit(&ptr,lsstore);
1190 	put32bit(&ptr,lstime);
1191 	put8bit(&ptr,lsstat);
1192 	put8bit(&ptr,0xFF);
1193 	put8bit(&ptr,0xFF);
1194 	put8bit(&ptr,0xFF);
1195 	put8bit(&ptr,0xFF);
1196 	put32bit(&ptr,0);
1197 	put32bit(&ptr,0);
1198 	put64bit(&ptr,meta_version());
1199 	put64bit(&ptr,exports_checksum());
1200 	put64bit(&ptr,main_utime());
1201 	put32bit(&ptr,0);
1202 }
1203 
matoclserv_memory_info(matoclserventry * eptr,const uint8_t * data,uint32_t length)1204 void matoclserv_memory_info(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
1205 	uint8_t *ptr;
1206 	uint64_t allocated[8];
1207 	uint64_t used[8];
1208 	(void)data;
1209 	if (length!=0) {
1210 		syslog(LOG_NOTICE,"CLTOMA_MEMORY_INFO - wrong size (%"PRIu32"/0)",length);
1211 		eptr->mode = KILL;
1212 		return;
1213 	}
1214 	ptr = matoclserv_createpacket(eptr,MATOCL_MEMORY_INFO,176);
1215 	chunk_get_memusage(allocated,used);
1216 	put64bit(&ptr,allocated[0]);
1217 	put64bit(&ptr,used[0]);
1218 	put64bit(&ptr,allocated[1]);
1219 	put64bit(&ptr,used[1]);
1220 	put64bit(&ptr,allocated[2]);
1221 	put64bit(&ptr,used[2]);
1222 	fs_get_memusage(allocated,used);
1223 	put64bit(&ptr,allocated[0]);
1224 	put64bit(&ptr,used[0]);
1225 	put64bit(&ptr,allocated[1]);
1226 	put64bit(&ptr,used[1]);
1227 	put64bit(&ptr,allocated[2]);
1228 	put64bit(&ptr,used[2]);
1229 	put64bit(&ptr,allocated[3]);
1230 	put64bit(&ptr,used[3]);
1231 	put64bit(&ptr,allocated[4]);
1232 	put64bit(&ptr,used[4]);
1233 	put64bit(&ptr,allocated[5]);
1234 	put64bit(&ptr,used[5]);
1235 	put64bit(&ptr,allocated[6]);
1236 	put64bit(&ptr,used[6]);
1237 	put64bit(&ptr,allocated[7]);
1238 	put64bit(&ptr,used[7]);
1239 }
1240 
matoclserv_fstest_info(matoclserventry * eptr,const uint8_t * data,uint32_t length)1241 void matoclserv_fstest_info(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
1242 	uint32_t loopstart,loopend,files,ugfiles,mfiles,mtfiles,msfiles,chunks,ugchunks,mchunks,msgbuffleng;
1243 	char *msgbuff;
1244 	uint8_t *ptr;
1245 	(void)data;
1246 	if (length!=0 && length!=1) {
1247 		syslog(LOG_NOTICE,"CLTOMA_FSTEST_INFO - wrong size (%"PRIu32"/0|1)",length);
1248 		eptr->mode = KILL;
1249 		return;
1250 	}
1251 	fs_test_getdata(&loopstart,&loopend,&files,&ugfiles,&mfiles,&mtfiles,&msfiles,&chunks,&ugchunks,&mchunks,&msgbuff,&msgbuffleng);
1252 	ptr = matoclserv_createpacket(eptr,MATOCL_FSTEST_INFO,msgbuffleng+((length==1)?44:36));
1253 	put32bit(&ptr,loopstart);
1254 	put32bit(&ptr,loopend);
1255 	put32bit(&ptr,files);
1256 	put32bit(&ptr,ugfiles);
1257 	put32bit(&ptr,mfiles);
1258 	if (length==1) {
1259 		put32bit(&ptr,mtfiles);
1260 		put32bit(&ptr,msfiles);
1261 	}
1262 	put32bit(&ptr,chunks);
1263 	put32bit(&ptr,ugchunks);
1264 	put32bit(&ptr,mchunks);
1265 	put32bit(&ptr,msgbuffleng);
1266 	if (msgbuffleng>0) {
1267 		memcpy(ptr,msgbuff,msgbuffleng);
1268 	}
1269 }
1270 
matoclserv_chunkstest_info(matoclserventry * eptr,const uint8_t * data,uint32_t length)1271 void matoclserv_chunkstest_info(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
1272 	uint8_t *ptr;
1273 	(void)data;
1274 	if (length!=0) {
1275 		syslog(LOG_NOTICE,"CLTOMA_CHUNKSTEST_INFO - wrong size (%"PRIu32"/0)",length);
1276 		eptr->mode = KILL;
1277 		return;
1278 	}
1279 	ptr = matoclserv_createpacket(eptr,MATOCL_CHUNKSTEST_INFO,72);
1280 	chunk_store_info(ptr);
1281 }
1282 
matoclserv_chunks_matrix(matoclserventry * eptr,const uint8_t * data,uint32_t length)1283 void matoclserv_chunks_matrix(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
1284 	uint8_t *ptr;
1285 	(void)data;
1286 	if (length>1) {
1287 		syslog(LOG_NOTICE,"CLTOMA_CHUNKS_MATRIX - wrong size (%"PRIu32"/0|1)",length);
1288 		eptr->mode = KILL;
1289 		return;
1290 	}
1291 	if (length==1) {
1292 		uint8_t matrixid;
1293 		matrixid = get8bit(&data);
1294 		ptr = matoclserv_createpacket(eptr,MATOCL_CHUNKS_MATRIX,484);
1295 		chunk_store_chunkcounters(ptr,matrixid);
1296 	} else {
1297 		uint8_t progressstatus;
1298 		ptr = matoclserv_createpacket(eptr,MATOCL_CHUNKS_MATRIX,969);
1299 		progressstatus = chunk_counters_in_progress();
1300 //		syslog(LOG_NOTICE,"progressstatus: %u",progressstatus);
1301 		put8bit(&ptr,progressstatus);
1302 		chunk_store_chunkcounters(ptr,0);
1303 		chunk_store_chunkcounters(ptr+484,1);
1304 	}
1305 }
1306 
matoclserv_quota_info(matoclserventry * eptr,const uint8_t * data,uint32_t length)1307 void matoclserv_quota_info(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
1308 	uint8_t *ptr;
1309 	(void)data;
1310 	if (length!=0) {
1311 		syslog(LOG_NOTICE,"CLTOMA_QUOTA_INFO - wrong size (%"PRIu32"/0)",length);
1312 		eptr->mode = KILL;
1313 		return;
1314 	}
1315 	ptr = matoclserv_createpacket(eptr,MATOCL_QUOTA_INFO,fs_getquotainfo(NULL));
1316 	fs_getquotainfo(ptr);
1317 }
1318 
matoclserv_exports_info(matoclserventry * eptr,const uint8_t * data,uint32_t length)1319 void matoclserv_exports_info(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
1320 	uint8_t *ptr;
1321 	uint8_t vmode;
1322 	if (length!=0 && length!=1) {
1323 		syslog(LOG_NOTICE,"CLTOMA_EXPORTS_INFO - wrong size (%"PRIu32"/0|1)",length);
1324 		eptr->mode = KILL;
1325 		return;
1326 	}
1327 	if (length==0) {
1328 		vmode = 0;
1329 	} else {
1330 		vmode = get8bit(&data);
1331 	}
1332 	ptr = matoclserv_createpacket(eptr,MATOCL_EXPORTS_INFO,exports_info_size(vmode));
1333 	exports_info_data(vmode,ptr);
1334 }
1335 
matoclserv_mlog_list(matoclserventry * eptr,const uint8_t * data,uint32_t length)1336 void matoclserv_mlog_list(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
1337 	uint8_t *ptr;
1338 	(void)data;
1339 	if (length!=0) {
1340 		syslog(LOG_NOTICE,"CLTOMA_MLOG_LIST - wrong size (%"PRIu32"/0)",length);
1341 		eptr->mode = KILL;
1342 		return;
1343 	}
1344 	ptr = matoclserv_createpacket(eptr,MATOCL_MLOG_LIST,matomlserv_mloglist_size());
1345 	matomlserv_mloglist_data(ptr);
1346 }
1347 
1348 
matoclserv_fuse_register(matoclserventry * eptr,const uint8_t * data,uint32_t length)1349 void matoclserv_fuse_register(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
1350 	const uint8_t *rptr;
1351 	uint8_t *wptr;
1352 	uint32_t sessionid;
1353 	uint8_t status;
1354 
1355 	if (length<64) {
1356 		syslog(LOG_NOTICE,"CLTOMA_FUSE_REGISTER - wrong size (%"PRIu32"/<64)",length);
1357 		eptr->mode = KILL;
1358 		return;
1359 	}
1360 	if (memcmp(data,FUSE_REGISTER_BLOB_ACL,64)==0) {
1361 		uint64_t expected_metaid;
1362 		uint32_t rootinode;
1363 		uint8_t sesflags;
1364 		uint16_t umaskval;
1365 		uint8_t mingoal,maxgoal;
1366 		uint32_t mintrashtime,maxtrashtime;
1367 		uint32_t disables;
1368 		uint32_t rootuid,rootgid;
1369 		uint32_t mapalluid,mapallgid;
1370 		uint32_t ileng,pleng;
1371 		uint8_t i,rcode,created;
1372 
1373 		if (length<65) {
1374 			syslog(LOG_NOTICE,"CLTOMA_FUSE_REGISTER/ACL - wrong size (%"PRIu32"/<65)",length);
1375 			eptr->mode = KILL;
1376 			return;
1377 		}
1378 
1379 		rptr = data+64;
1380 		rcode = get8bit(&rptr);
1381 
1382 		if ((eptr->registered==0 && rcode==REGISTER_CLOSESESSION) || (eptr->registered && rcode!=REGISTER_CLOSESESSION)) {
1383 			syslog(LOG_NOTICE,"CLTOMA_FUSE_REGISTER/ACL - wrong rcode (%d) for registered status (%d)",rcode,eptr->registered);
1384 			eptr->mode = KILL;
1385 			return;
1386 		}
1387 
1388 //		printf("rcode: %d\n",rcode);
1389 //
1390 		switch (rcode) {
1391 		case REGISTER_GETRANDOM:
1392 			if (length!=65) {
1393 				syslog(LOG_NOTICE,"CLTOMA_FUSE_REGISTER/ACL.1 - wrong size (%"PRIu32"/65)",length);
1394 				eptr->mode = KILL;
1395 				return;
1396 			}
1397 			wptr = matoclserv_createpacket(eptr,MATOCL_FUSE_REGISTER,32);
1398 			for (i=0 ; i<32 ; i++) {
1399 				eptr->passwordrnd[i]=rndu8();
1400 			}
1401 			memcpy(wptr,eptr->passwordrnd,32);
1402 			return;
1403 		case REGISTER_NEWSESSION:
1404 			if (length<77) {
1405 				syslog(LOG_NOTICE,"CLTOMA_FUSE_REGISTER/ACL.2 - wrong size (%"PRIu32"/>=77)",length);
1406 				eptr->mode = KILL;
1407 				return;
1408 			}
1409 			eptr->version = get32bit(&rptr);
1410 			eptr->asize = (eptr->version>=VERSION2INT(3,0,93))?ATTR_RECORD_SIZE:35;
1411 
1412 			ileng = get32bit(&rptr);
1413 			if (length<77+ileng) {
1414 				syslog(LOG_NOTICE,"CLTOMA_FUSE_REGISTER/ACL.2 - wrong size (%"PRIu32"/>=77+ileng(%"PRIu32"))",length,ileng);
1415 				eptr->mode = KILL;
1416 				return;
1417 			}
1418 			if (eptr->info!=NULL) {
1419 				free(eptr->info);
1420 			}
1421 			eptr->ileng = ileng;
1422 			eptr->info = malloc(ileng);
1423 			passert(eptr->info);
1424 			memcpy(eptr->info,rptr,ileng);
1425 			rptr+=ileng;
1426 
1427 			pleng = get32bit(&rptr);
1428 			if (length!=77+ileng+pleng && length!=77+16+ileng+pleng && length!=77+4+ileng+pleng && length!=77+4+16+ileng+pleng && length!=77+12+ileng+pleng && length!=77+12+16+ileng+pleng) {
1429 				syslog(LOG_NOTICE,"CLTOMA_FUSE_REGISTER/ACL.2 - wrong size (%"PRIu32"/77+ileng(%"PRIu32")+pleng(%"PRIu32")+[0|4|12]+[0|16])",length,ileng,pleng);
1430 				eptr->mode = KILL;
1431 				return;
1432 			}
1433 			if (eptr->path!=NULL) {
1434 				free(eptr->path);
1435 			}
1436 			if (pleng>0) {
1437 				eptr->path = malloc(pleng);
1438 				passert(eptr->path);
1439 				memcpy(eptr->path,rptr,pleng);
1440 				rptr+=pleng;
1441 				if (rptr[-1]!=0) {
1442 					syslog(LOG_NOTICE,"CLTOMA_FUSE_REGISTER/ACL.2 - received path without ending zero");
1443 					eptr->mode = KILL;
1444 					return;
1445 				}
1446 			} else {
1447 				eptr->path = malloc(1);
1448 				passert(eptr->path);
1449 				eptr->path[0] = 0;
1450 			}
1451 
1452 			if (length==77+4+ileng+pleng || length==77+4+16+ileng+pleng) {
1453 				sessionid = get32bit(&rptr);
1454 			} else if (length==77+12+ileng+pleng || length==77+12+16+ileng+pleng) {
1455 				sessionid = get32bit(&rptr);
1456 				expected_metaid = get64bit(&rptr);
1457 				if (expected_metaid != meta_get_id()) {
1458 					sessionid = 0;
1459 				}
1460 			} else {
1461 				sessionid = iptosesid_get(eptr->peerip); // patch for clients < 3.0
1462 			}
1463 			if (length>=77+16+ileng+pleng) {
1464 				eptr->usepassword = 1;
1465 				memcpy(eptr->passwordmd5,rptr,16);
1466 				status = exports_check(eptr->peerip,eptr->version,eptr->path,eptr->passwordrnd,rptr,&sesflags,&umaskval,&rootuid,&rootgid,&mapalluid,&mapallgid,&mingoal,&maxgoal,&mintrashtime,&maxtrashtime,&disables);
1467 			} else {
1468 				eptr->usepassword = 0;
1469 				status = exports_check(eptr->peerip,eptr->version,eptr->path,NULL,NULL,&sesflags,&umaskval,&rootuid,&rootgid,&mapalluid,&mapallgid,&mingoal,&maxgoal,&mintrashtime,&maxtrashtime,&disables);
1470 			}
1471 			if (status==MFS_STATUS_OK) {
1472 				status = fs_getrootinode(&rootinode,eptr->path);
1473 			}
1474 			created = 0;
1475 			if (status==MFS_STATUS_OK) {
1476 				if (sessionid!=0) {
1477 					eptr->sesdata = sessions_find_session(sessionid);
1478 					if (eptr->sesdata==NULL) {
1479 						sessionid=0;
1480 					} else {
1481 						sessions_chg_session(eptr->sesdata,exports_checksum(),rootinode,sesflags,umaskval,rootuid,rootgid,mapalluid,mapallgid,mingoal,maxgoal,mintrashtime,maxtrashtime,disables,eptr->peerip,eptr->info,eptr->ileng);
1482 					}
1483 				}
1484 				if (sessionid==0) {
1485 					eptr->sesdata = sessions_new_session(exports_checksum(),rootinode,sesflags,umaskval,rootuid,rootgid,mapalluid,mapallgid,mingoal,maxgoal,mintrashtime,maxtrashtime,disables,eptr->peerip,eptr->info,eptr->ileng);
1486 					created = 1;
1487 				}
1488 				if (eptr->sesdata==NULL) {
1489 					syslog(LOG_NOTICE,"can't allocate session record");
1490 					eptr->mode = KILL;
1491 					return;
1492 				}
1493 			}
1494 			wptr = matoclserv_createpacket(eptr,MATOCL_FUSE_REGISTER,(status==MFS_STATUS_OK)?((eptr->version>=VERSION2INT(3,0,112))?49:(eptr->version>=VERSION2INT(3,0,72))?45:(eptr->version>=VERSION2INT(3,0,11))?43:(eptr->version>=VERSION2INT(1,6,26))?35:(eptr->version>=VERSION2INT(1,6,21))?25:(eptr->version>=VERSION2INT(1,6,1))?21:13):1);
1495 			if (status!=MFS_STATUS_OK) {
1496 				put8bit(&wptr,status);
1497 				eptr->sesdata = NULL;
1498 				return;
1499 			}
1500 			sessionid = sessions_get_id(eptr->sesdata);
1501 			if (eptr->version==VERSION2INT(1,6,21)) {
1502 				put32bit(&wptr,0);
1503 			} else if (eptr->version>=VERSION2INT(1,6,22)) {
1504 				put16bit(&wptr,VERSMAJ);
1505 				put8bit(&wptr,VERSMID);
1506 				put8bit(&wptr,VERSMIN);
1507 			}
1508 			put32bit(&wptr,sessionid);
1509 			if (eptr->version>=VERSION2INT(3,0,11)) {
1510 				put64bit(&wptr,meta_get_id());
1511 			}
1512 			put8bit(&wptr,sesflags);
1513 			if (eptr->version>=VERSION2INT(3,0,72)) {
1514 				put16bit(&wptr,umaskval);
1515 			}
1516 			put32bit(&wptr,rootuid);
1517 			put32bit(&wptr,rootgid);
1518 			if (eptr->version>=VERSION2INT(1,6,1)) {
1519 				put32bit(&wptr,mapalluid);
1520 				put32bit(&wptr,mapallgid);
1521 			}
1522 			if (eptr->version>=VERSION2INT(1,6,26)) {
1523 				put8bit(&wptr,mingoal);
1524 				put8bit(&wptr,maxgoal);
1525 				put32bit(&wptr,mintrashtime);
1526 				put32bit(&wptr,maxtrashtime);
1527 			}
1528 			if (eptr->version>=VERSION2INT(3,0,112)) {
1529 				put32bit(&wptr,disables);
1530 			}
1531 			sessions_attach_session(eptr->sesdata,eptr->peerip,eptr->version);
1532 			eptr->registered = 1;
1533 			if (created) {
1534 				syslog(LOG_NOTICE,"created new sessionid:%"PRIu32,sessionid);
1535 			}
1536 			return;
1537 		case REGISTER_NEWMETASESSION:
1538 			if (length<73) {
1539 				syslog(LOG_NOTICE,"CLTOMA_FUSE_REGISTER/ACL.5 - wrong size (%"PRIu32"/>=73)",length);
1540 				eptr->mode = KILL;
1541 				return;
1542 			}
1543 			eptr->version = get32bit(&rptr);
1544 			eptr->asize = (eptr->version>=VERSION2INT(3,0,93))?ATTR_RECORD_SIZE:35;
1545 
1546 			ileng = get32bit(&rptr);
1547 			if (length!=73+ileng && length!=73+16+ileng && length!=73+4+ileng && length!=73+4+16+ileng && length!=73+12+ileng && length!=73+12+16+ileng) {
1548 				syslog(LOG_NOTICE,"CLTOMA_FUSE_REGISTER/ACL.5 - wrong size (%"PRIu32"/73+ileng(%"PRIu32")+[0|4|12]+[0|16])",length,ileng);
1549 				eptr->mode = KILL;
1550 				return;
1551 			}
1552 			if (eptr->info!=NULL) {
1553 				free(eptr->info);
1554 			}
1555 			eptr->ileng = ileng;
1556 			eptr->info = malloc(ileng);
1557 			passert(eptr->info);
1558 			memcpy(eptr->info,rptr,ileng);
1559 			rptr+=ileng;
1560 
1561 			if (eptr->path!=NULL) {
1562 				free(eptr->path);
1563 				eptr->path = NULL;
1564 			}
1565 
1566 			if (length==73+4+ileng || length==73+4+16+ileng) {
1567 				sessionid = get32bit(&rptr);
1568 			} else if (length==73+12+ileng || length==73+12+16+ileng) {
1569 				sessionid = get32bit(&rptr);
1570 				expected_metaid = get64bit(&rptr);
1571 				if (expected_metaid != meta_get_id()) {
1572 					sessionid = 0;
1573 				}
1574 			} else {
1575 				sessionid = iptosesid_get(eptr->peerip); // patch for clients < 3.0
1576 			}
1577 			if (length>=73+16+ileng) {
1578 				eptr->usepassword = 1;
1579 				memcpy(eptr->passwordmd5,rptr,16);
1580 				status = exports_check(eptr->peerip,eptr->version,NULL,eptr->passwordrnd,rptr,&sesflags,&umaskval,&rootuid,&rootgid,&mapalluid,&mapallgid,&mingoal,&maxgoal,&mintrashtime,&maxtrashtime,&disables);
1581 			} else {
1582 				eptr->usepassword = 0;
1583 				status = exports_check(eptr->peerip,eptr->version,NULL,NULL,NULL,&sesflags,&umaskval,&rootuid,&rootgid,&mapalluid,&mapallgid,&mingoal,&maxgoal,&mintrashtime,&maxtrashtime,&disables);
1584 			}
1585 			if (status==MFS_STATUS_OK) {
1586 				if (sessionid!=0) {
1587 					eptr->sesdata = sessions_find_session(sessionid);
1588 					if (eptr->sesdata==NULL) {
1589 						sessionid=0;
1590 					} else {
1591 						sessions_chg_session(eptr->sesdata,exports_checksum(),0,sesflags,umaskval,0,0,0,0,mingoal,maxgoal,mintrashtime,maxtrashtime,disables,eptr->peerip,eptr->info,eptr->ileng);
1592 					}
1593 				}
1594 				if (sessionid==0) {
1595 					eptr->sesdata = sessions_new_session(exports_checksum(),0,sesflags,umaskval,0,0,0,0,mingoal,maxgoal,mintrashtime,maxtrashtime,disables,eptr->peerip,eptr->info,eptr->ileng);
1596 				}
1597 				if (eptr->sesdata==NULL) {
1598 					syslog(LOG_NOTICE,"can't allocate session record");
1599 					eptr->mode = KILL;
1600 					return;
1601 				}
1602 			}
1603 			wptr = matoclserv_createpacket(eptr,MATOCL_FUSE_REGISTER,(status==MFS_STATUS_OK)?((eptr->version>=VERSION2INT(3,0,11))?27:(eptr->version>=VERSION2INT(1,6,26))?19:(eptr->version>=VERSION2INT(1,6,21))?9:5):1);
1604 			if (status!=MFS_STATUS_OK) {
1605 				put8bit(&wptr,status);
1606 				eptr->sesdata = NULL;
1607 				return;
1608 			}
1609 			sessionid = sessions_get_id(eptr->sesdata);
1610 			if (eptr->version>=VERSION2INT(1,6,21)) {
1611 				put16bit(&wptr,VERSMAJ);
1612 				put8bit(&wptr,VERSMID);
1613 				put8bit(&wptr,VERSMIN);
1614 			}
1615 			put32bit(&wptr,sessionid);
1616 			if (eptr->version>=VERSION2INT(3,0,11)) {
1617 				put64bit(&wptr,meta_get_id());
1618 			}
1619 			put8bit(&wptr,sesflags);
1620 			if (eptr->version>=VERSION2INT(1,6,26)) {
1621 				put8bit(&wptr,mingoal);
1622 				put8bit(&wptr,maxgoal);
1623 				put32bit(&wptr,mintrashtime);
1624 				put32bit(&wptr,maxtrashtime);
1625 			}
1626 			sessions_attach_session(eptr->sesdata,eptr->peerip,eptr->version);
1627 			eptr->registered = 1;
1628 			return;
1629 		case REGISTER_RECONNECT:
1630 		case REGISTER_TOOLS:
1631 			if (length<73) {
1632 				syslog(LOG_NOTICE,"CLTOMA_FUSE_REGISTER/ACL.%"PRIu8" - wrong size (%"PRIu32"/73)",rcode,length);
1633 				eptr->mode = KILL;
1634 				return;
1635 			}
1636 
1637 			sessionid = get32bit(&rptr);
1638 			if (iptosesid_check(eptr->peerip)) { // patch for clients < 3.0
1639 				eptr->mode = KILL;
1640 				return;
1641 			}
1642 
1643 			eptr->version = get32bit(&rptr);
1644 			eptr->asize = (eptr->version>=VERSION2INT(3,0,93))?ATTR_RECORD_SIZE:35;
1645 
1646 			status = MFS_STATUS_OK;
1647 			if (length>=81) {
1648 				expected_metaid = get64bit(&rptr);
1649 				if (expected_metaid!=meta_get_id()) {
1650 					status = MFS_ERROR_BADSESSIONID;
1651 				}
1652 			}
1653 			if (status==MFS_STATUS_OK) {
1654 				eptr->sesdata = sessions_find_session(sessionid);
1655 //				syslog(LOG_WARNING,"session reconnect: ip:%u.%u.%u.%u ; version:%u.%u.%u ; sessionid: %u (%s)",(eptr->peerip>>24)&0xFF,(eptr->peerip>>16)&0xFF,(eptr->peerip>>8)&0xFF,eptr->peerip&0xFF,eptr->version>>16,(eptr->version>>8)&0xFF,(eptr->version>>1)&0x7F,sessionid,(eptr->sesdata)?"found":"not found");
1656 				if (eptr->sesdata==NULL || sessions_get_peerip(eptr->sesdata)==0) { // no such session or session created by entries in metadata
1657 					status = MFS_ERROR_BADSESSIONID;
1658 				} else {
1659 //					syslog(LOG_NOTICE,"session exports checksum: %016"PRIX64" ; current exports checksum: %016"PRIX64,sessions_get_exportscsum(eptr->sesdata),exports_checksum());
1660 //					syslog(LOG_WARNING,"session reconnect: ip:%u.%u.%u.%u (%08X) ; session_peerip(%08X)",(eptr->peerip>>24)&0xFF,(eptr->peerip>>16)&0xFF,(eptr->peerip>>8)&0xFF,eptr->peerip&0xFF,eptr->peerip,sessions_get_peerip(eptr->sesdata));
1661 					if (sessions_get_exportscsum(eptr->sesdata)!=exports_checksum() || ((sessions_get_sesflags(eptr->sesdata)&SESFLAG_DYNAMICIP)==0 && eptr->peerip!=sessions_get_peerip(eptr->sesdata))) {
1662 						status = MFS_ERROR_EPERM; // masters < 2.1.0 returned MFS_ERROR_EACCES, so MFS_ERROR_EPERM means that client can use register with sessionid
1663 						iptosesid_add(eptr->peerip,sessionid); // patch for clients < 3.0
1664 					}
1665 				}
1666 			}
1667 			if (rcode==REGISTER_RECONNECT && eptr->version>=VERSION2INT(3,0,95)) {
1668 				wptr = matoclserv_createpacket(eptr,MATOCL_FUSE_REGISTER,5);
1669 				put16bit(&wptr,VERSMAJ);
1670 				put8bit(&wptr,VERSMID);
1671 				put8bit(&wptr,VERSMIN);
1672 			} else {
1673 				wptr = matoclserv_createpacket(eptr,MATOCL_FUSE_REGISTER,1);
1674 			}
1675 			put8bit(&wptr,status);
1676 			if (status!=MFS_STATUS_OK) {
1677 				eptr->sesdata = NULL;
1678 				return;
1679 			}
1680 			sessions_attach_session(eptr->sesdata,eptr->peerip,eptr->version);
1681 			eptr->registered = (rcode==3)?1:100;
1682 			return;
1683 		case REGISTER_CLOSESESSION:
1684 			if (length<69) {
1685 				syslog(LOG_NOTICE,"CLTOMA_FUSE_REGISTER/ACL.6 - wrong size (%"PRIu32"/69)",length);
1686 				eptr->mode = KILL;
1687 				return;
1688 			}
1689 			sessionid = get32bit(&rptr);
1690 			status = MFS_STATUS_OK;
1691 			if (length>=77) {
1692 				expected_metaid = get64bit(&rptr);
1693 				if (expected_metaid!=meta_get_id()) {
1694 					status = MFS_ERROR_BADSESSIONID;
1695 				}
1696 			}
1697 			if (status==MFS_STATUS_OK) {
1698 				sessions_close_session(sessionid);
1699 			}
1700 			if (eptr->version>=VERSION2INT(1,7,29)) {
1701 				wptr = matoclserv_createpacket(eptr,MATOCL_FUSE_REGISTER,1);
1702 				put8bit(&wptr,status);
1703 			}
1704 			eptr->mode = FINISH;
1705 			return;
1706 		}
1707 		syslog(LOG_NOTICE,"CLTOMA_FUSE_REGISTER/ACL - wrong rcode (%"PRIu8")",rcode);
1708 		eptr->mode = KILL;
1709 		return;
1710 	} else {
1711 		syslog(LOG_NOTICE,"CLTOMA_FUSE_REGISTER - wrong register blob");
1712 		eptr->mode = KILL;
1713 		return;
1714 	}
1715 }
1716 
matoclserv_reload_sessions(void)1717 void matoclserv_reload_sessions(void) {
1718 	matoclserventry *eptr;
1719 
1720 	exports_reload();
1721 	for (eptr=matoclservhead ; eptr ; eptr=eptr->next) {
1722 		if (eptr->mode==DATA && eptr->registered==1 && eptr->sesdata!=NULL) {
1723 			if (sessions_get_exportscsum(eptr->sesdata)!=exports_checksum()) {
1724 				eptr->mode = KILL;
1725 			}
1726 		}
1727 	}
1728 }
1729 
matoclserv_fuse_sustained_inodes(matoclserventry * eptr,const uint8_t * data,uint32_t length)1730 void matoclserv_fuse_sustained_inodes(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
1731 	const uint8_t *rptr;
1732 	static uint32_t *inodetab = NULL;
1733 	static uint32_t inodetabsize = 0;
1734 	uint32_t i,j;
1735 
1736 	if ((length&0x3)!=0) {
1737 		syslog(LOG_NOTICE,"CLTOMA_FUSE_SUSTAINED_INODES - wrong size (%"PRIu32"/N*4)",length);
1738 		eptr->mode = KILL;
1739 		return;
1740 	}
1741 
1742 	if (eptr->sesdata==NULL) {
1743 		syslog(LOG_NOTICE,"CLTOMA_FUSE_SUSTAINED_INODES - session doesn't exist");
1744 		eptr->mode = KILL;
1745 		return;
1746 	}
1747 	length>>=2;
1748 	if (length>inodetabsize) {
1749 		if (inodetab) {
1750 			free(inodetab);
1751 		}
1752 		inodetabsize = ((length+0xFF)&0xFFFFFF00);
1753 		inodetab = malloc(sizeof(uint32_t)*inodetabsize);
1754 		passert(inodetab);
1755 	}
1756 	rptr = data;
1757 	j = 0;
1758 	while (length>0) {
1759 		i = get32bit(&rptr);
1760 		if (i>0) {
1761 			inodetab[j] = i;
1762 			j++;
1763 		}
1764 		length--;
1765 	}
1766 	of_sync(sessions_get_id(eptr->sesdata),inodetab,j);
1767 //	sessions_sync_open_files(eptr->sesdata,data,length>>2);
1768 }
1769 
matoclserv_fuse_amtime_inodes(matoclserventry * eptr,const uint8_t * data,uint32_t length)1770 void matoclserv_fuse_amtime_inodes(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
1771 	const uint8_t *rptr;
1772 	static uint32_t *inodetab=NULL,*atimetab=NULL,*mtimetab=NULL;
1773 	static uint32_t tabsizes = 0;
1774 	uint32_t i,a,m,j;
1775 
1776 	if ((length%12)!=0) {
1777 		syslog(LOG_NOTICE,"CLTOMA_FUSE_AMTIME_INODES - wrong size (%"PRIu32"/N*12)",length);
1778 		eptr->mode = KILL;
1779 		return;
1780 	}
1781 
1782 	if (eptr->sesdata==NULL) {
1783 		syslog(LOG_NOTICE,"CLTOMA_FUSE_AMTIME_INODES - session doesn't exist");
1784 		eptr->mode = KILL;
1785 		return;
1786 	}
1787 	length/=12;
1788 	if (length>tabsizes) {
1789 		if (inodetab) {
1790 			free(inodetab);
1791 		}
1792 		if (atimetab) {
1793 			free(atimetab);
1794 		}
1795 		if (mtimetab) {
1796 			free(mtimetab);
1797 		}
1798 		tabsizes = ((length+0xFF)&0xFFFFFF00);
1799 		inodetab = malloc(sizeof(uint32_t)*tabsizes);
1800 		passert(inodetab);
1801 		atimetab = malloc(sizeof(uint32_t)*tabsizes);
1802 		passert(atimetab);
1803 		mtimetab = malloc(sizeof(uint32_t)*tabsizes);
1804 		passert(mtimetab);
1805 	}
1806 	rptr = data;
1807 	j = 0;
1808 	while (length>0) {
1809 		i = get32bit(&rptr);
1810 		a = get32bit(&rptr);
1811 		m = get32bit(&rptr);
1812 		if (i>0 && (a>0 || m>0)) {
1813 			inodetab[j] = i;
1814 			atimetab[j] = a;
1815 			mtimetab[j] = m;
1816 			j++;
1817 		}
1818 		length--;
1819 	}
1820 	fs_amtime_update(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inodetab,atimetab,mtimetab,j);
1821 }
1822 
matoclserv_fuse_time_sync(matoclserventry * eptr,const uint8_t * data,uint32_t length)1823 void matoclserv_fuse_time_sync(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
1824 	uint8_t *ptr;
1825 	uint32_t msgid;
1826 
1827 	if (length!=0 && length!=4) {
1828 		syslog(LOG_NOTICE,"CLTOMA_FUSE_TIME_SYNC - wrong size (%"PRIu32"/0)",length);
1829 		eptr->mode = KILL;
1830 		return;
1831 	}
1832 
1833 	if (length==4) {
1834 		msgid = get32bit(&data);
1835 	} else {
1836 		msgid = 0;
1837 	}
1838 
1839 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_TIME_SYNC,8+length);
1840 	if (length==4) {
1841 		put32bit(&ptr,msgid);
1842 	}
1843 	put64bit(&ptr,main_utime());
1844 }
1845 
matoclserv_gid_storage(uint32_t gids)1846 uint32_t* matoclserv_gid_storage(uint32_t gids) {
1847 	static uint32_t *gid=NULL;
1848 	static uint32_t gidleng=0;
1849 	if (gids==0) {
1850 		if (gid!=NULL) {
1851 			free(gid);
1852 		}
1853 		gidleng=0;
1854 		return NULL;
1855 	} else {
1856 		if (gidleng<gids) {
1857 			gidleng = (gids+255)&UINT32_C(0xFFFFFF00);
1858 			if (gid!=NULL) {
1859 				free(gid);
1860 			}
1861 			gid = malloc(sizeof(uint32_t)*gidleng);
1862 			passert(gid);
1863 		}
1864 		return gid;
1865 	}
1866 }
1867 
matoclserv_fuse_statfs(matoclserventry * eptr,const uint8_t * data,uint32_t length)1868 void matoclserv_fuse_statfs(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
1869 	uint64_t totalspace,availspace,freespace,trashspace,sustainedspace;
1870 	uint32_t msgid,inodes;
1871 	uint8_t addfreespace;
1872 	uint8_t *ptr;
1873 	if (length!=4) {
1874 		syslog(LOG_NOTICE,"CLTOMA_FUSE_STATFS - wrong size (%"PRIu32"/4)",length);
1875 		eptr->mode = KILL;
1876 		return;
1877 	}
1878 	addfreespace = ((eptr->version>=VERSION2INT(3,0,102) && eptr->version<VERSION2INT(4,0,0)) || eptr->version>=VERSION2INT(4,9,0))?1:0;
1879 	msgid = get32bit(&data);
1880 	fs_statfs(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),&totalspace,&availspace,&freespace,&trashspace,&sustainedspace,&inodes);
1881 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_STATFS,addfreespace?48:40);
1882 	put32bit(&ptr,msgid);
1883 	put64bit(&ptr,totalspace);
1884 	put64bit(&ptr,availspace);
1885 	if (addfreespace) {
1886 		put64bit(&ptr,freespace);
1887 	}
1888 	put64bit(&ptr,trashspace);
1889 	put64bit(&ptr,sustainedspace);
1890 	put32bit(&ptr,inodes);
1891 	sessions_inc_stats(eptr->sesdata,0);
1892 }
1893 
matoclserv_fuse_access(matoclserventry * eptr,const uint8_t * data,uint32_t length)1894 void matoclserv_fuse_access(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
1895 	uint32_t *gid;
1896 	uint32_t i;
1897 	uint32_t inode,uid,gids;
1898 	uint16_t modemask;
1899 	uint32_t msgid;
1900 	uint8_t *ptr;
1901 	uint8_t status;
1902 	if ((length&1)==1) {
1903 		if (length!=17) {
1904 			syslog(LOG_NOTICE,"CLTOMA_FUSE_ACCESS - wrong size (%"PRIu32"/17)",length);
1905 			eptr->mode = KILL;
1906 			return;
1907 		}
1908 		msgid = get32bit(&data);
1909 		inode = get32bit(&data);
1910 		uid = get32bit(&data);
1911 		gid = matoclserv_gid_storage(1);
1912 		gid[0] = get32bit(&data);
1913 		gids = 1;
1914 		sessions_ugid_remap(eptr->sesdata,&uid,gid);
1915 		modemask = get8bit(&data);
1916 	} else {
1917 		if (length<18) {
1918 			syslog(LOG_NOTICE,"CLTOMA_FUSE_ACCESS - wrong size (%"PRIu32"/18+4*N)",length);
1919 			eptr->mode = KILL;
1920 			return;
1921 		}
1922 		msgid = get32bit(&data);
1923 		inode = get32bit(&data);
1924 		uid = get32bit(&data);
1925 		gids = get32bit(&data);
1926 		if (length!=18+gids*4) {
1927 			syslog(LOG_NOTICE,"CLTOMA_FUSE_ACCESS - wrong size (%"PRIu32"/18+4*N)",length);
1928 			eptr->mode = KILL;
1929 			return;
1930 		}
1931 		gid = matoclserv_gid_storage(gids);
1932 		for (i=0 ; i<gids ; i++) {
1933 			gid[i] = get32bit(&data);
1934 		}
1935 		sessions_ugid_remap(eptr->sesdata,&uid,gid);
1936 		modemask = get16bit(&data);
1937 	}
1938 	status = fs_access(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,uid,gids,gid,modemask);
1939 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_ACCESS,5);
1940 	put32bit(&ptr,msgid);
1941 	put8bit(&ptr,status);
1942 }
1943 
matoclserv_fuse_lookup(matoclserventry * eptr,const uint8_t * data,uint32_t length)1944 void matoclserv_fuse_lookup(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
1945 	uint32_t inode,uid,gids,auid,agid;
1946 	uint32_t *gid;
1947 	uint32_t i;
1948 	uint8_t nleng;
1949 	const uint8_t *name;
1950 	uint32_t newinode;
1951 	uint8_t attr[ATTR_RECORD_SIZE];
1952 	uint16_t lflags;
1953 	uint16_t accmode;
1954 	uint8_t filenode;
1955 	uint8_t validchunk;
1956 	uint64_t chunkid;
1957 	uint32_t msgid;
1958 	uint8_t *ptr;
1959 	uint8_t status;
1960 	if (length<17) {
1961 		syslog(LOG_NOTICE,"CLTOMA_FUSE_LOOKUP - wrong size (%"PRIu32")",length);
1962 		eptr->mode = KILL;
1963 		return;
1964 	}
1965 	msgid = get32bit(&data);
1966 	inode = get32bit(&data);
1967 	nleng = get8bit(&data);
1968 	if (length<17U+nleng) {
1969 		syslog(LOG_NOTICE,"CLTOMA_FUSE_LOOKUP - wrong size (%"PRIu32":nleng=%"PRIu8")",length,nleng);
1970 		eptr->mode = KILL;
1971 		return;
1972 	}
1973 	name = data;
1974 	data += nleng;
1975 	auid = uid = get32bit(&data);
1976 	if (length==17U+nleng) {
1977 		gids = 1;
1978 		gid = matoclserv_gid_storage(gids);
1979 		agid = gid[0] = get32bit(&data);
1980 		sessions_ugid_remap(eptr->sesdata,&uid,gid);
1981 	} else {
1982 		gids = get32bit(&data);
1983 		if (length!=17U+nleng+4*gids) {
1984 			syslog(LOG_NOTICE,"CLTOMA_FUSE_LOOKUP - wrong size (%"PRIu32":nleng=%"PRIu8":gids=%"PRIu32")",length,nleng,gids);
1985 			eptr->mode = KILL;
1986 			return;
1987 		}
1988 		gid = matoclserv_gid_storage(gids);
1989 		for (i=0 ; i<gids ; i++) {
1990 			gid[i] = get32bit(&data);
1991 		}
1992 		agid = gid[0];
1993 		sessions_ugid_remap(eptr->sesdata,&uid,gid);
1994 	}
1995 	if (eptr->version>=VERSION2INT(3,0,40)) {
1996 		uint8_t sesflags = sessions_get_sesflags(eptr->sesdata);
1997 		status = fs_lookup(sessions_get_rootinode(eptr->sesdata),sesflags,inode,nleng,name,uid,gids,gid,auid,agid,&newinode,attr,&accmode,&filenode,&validchunk,&chunkid);
1998 		if (status==MFS_STATUS_OK) {
1999 			uint32_t version;
2000 			uint8_t count;
2001 			uint8_t cs_data[100*14];
2002 			lflags = (accmode & LOOKUP_ACCESS_BITS);
2003 			count = 0;
2004 			version = 0;
2005 			if (eptr->version<VERSION2INT(3,0,113) && lflags&LOOKUP_APPENDONLY) { // this mount doesn't support append only, so remove 'W' access
2006 				lflags &= LOOKUP_ACCESS_MODES_RO;
2007 			}
2008 			if (filenode && (lflags&LOOKUP_ACCESS_MODES_IO)!=0) { // can be read and/or written
2009 				if (eptr->version>=VERSION2INT(3,0,113)) {
2010 					if ((lflags&LOOKUP_DIRECTMODE)==0) {
2011 						if (dcm_open(newinode,sessions_get_id(eptr->sesdata))) {
2012 							lflags |= LOOKUP_KEEPCACHE;
2013 						} else { // just fix for old clients
2014 							if (sesflags&SESFLAG_ATTRBIT) {
2015 								attr[0]&=(0xFF^MATTR_ALLOWDATACACHE);
2016 							} else {
2017 								attr[1]&=(0xFF^(MATTR_ALLOWDATACACHE<<4));
2018 							}
2019 						}
2020 					}
2021 				} else {
2022 					if ((sesflags&SESFLAG_ATTRBIT)==0 || (attr[0]&MATTR_DIRECTMODE)==0) {
2023 						if (dcm_open(newinode,sessions_get_id(eptr->sesdata))==0) {
2024 							if (sesflags&SESFLAG_ATTRBIT) {
2025 								attr[0]&=(0xFF^MATTR_ALLOWDATACACHE);
2026 							} else {
2027 								attr[1]&=(0xFF^(MATTR_ALLOWDATACACHE<<4));
2028 							}
2029 						}
2030 					}
2031 				}
2032 				if (validchunk && (sessions_get_disables(eptr->sesdata)&DISABLE_READ)==0) {
2033 					if (chunkid>0) {
2034 						if (chunk_get_version_and_csdata(2,chunkid,eptr->peerip,&version,&count,cs_data)==MFS_STATUS_OK) {
2035 							lflags |= LOOKUP_CHUNK_ZERO_DATA;
2036 						}
2037 					} else {
2038 						version = 0;
2039 						count = 0;
2040 						lflags |= LOOKUP_CHUNK_ZERO_DATA;
2041 					}
2042 				}
2043 			}
2044 			if (sesflags&SESFLAG_READONLY) {
2045 				lflags |= LOOKUP_RO_FILESYSTEM;
2046 			}
2047 			if (lflags & LOOKUP_CHUNK_ZERO_DATA) {
2048 				ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_LOOKUP,eptr->asize+23+count*14);
2049 				put32bit(&ptr,msgid);
2050 				put32bit(&ptr,newinode);
2051 				memcpy(ptr,attr,eptr->asize);
2052 				ptr+=eptr->asize;
2053 				put16bit(&ptr,lflags);
2054 				put8bit(&ptr,2);
2055 				put64bit(&ptr,chunkid);
2056 				put32bit(&ptr,version);
2057 				if (count>0) {
2058 					memcpy(ptr,cs_data,count*14);
2059 				}
2060 			} else {
2061 				ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_LOOKUP,eptr->asize+10);
2062 				put32bit(&ptr,msgid);
2063 				put32bit(&ptr,newinode);
2064 				memcpy(ptr,attr,eptr->asize);
2065 				ptr+=eptr->asize;
2066 				put16bit(&ptr,lflags);
2067 			}
2068 		}
2069 	} else {
2070 		status = fs_lookup(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,nleng,name,uid,gids,gid,auid,agid,&newinode,attr,NULL,NULL,NULL,NULL);
2071 		if (status==MFS_ERROR_ENOENT_NOCACHE && eptr->version<VERSION2INT(3,0,25)) {
2072 			status = MFS_ERROR_ENOENT;
2073 		}
2074 		if (status==MFS_STATUS_OK) {
2075 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_LOOKUP,eptr->asize+8);
2076 			put32bit(&ptr,msgid);
2077 			put32bit(&ptr,newinode);
2078 			memcpy(ptr,attr,eptr->asize);
2079 		}
2080 	}
2081 	if (status!=MFS_STATUS_OK) {
2082 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_LOOKUP,5);
2083 		put32bit(&ptr,msgid);
2084 		put8bit(&ptr,status);
2085 	}
2086 	sessions_inc_stats(eptr->sesdata,3);
2087 }
2088 
matoclserv_fuse_getattr(matoclserventry * eptr,const uint8_t * data,uint32_t length)2089 void matoclserv_fuse_getattr(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
2090 	uint32_t inode,uid,gid,auid,agid;
2091 	uint8_t opened;
2092 	uint8_t attr[ATTR_RECORD_SIZE];
2093 	uint32_t msgid;
2094 	uint8_t *ptr;
2095 	uint8_t status;
2096 	if (length!=8 && length!=16 && length!=17) {
2097 		syslog(LOG_NOTICE,"CLTOMA_FUSE_GETATTR - wrong size (%"PRIu32"/8|16|17)",length);
2098 		eptr->mode = KILL;
2099 		return;
2100 	}
2101 	msgid = get32bit(&data);
2102 	inode = get32bit(&data);
2103 	if (length==17) {
2104 		opened = get8bit(&data);
2105 	} else {
2106 		opened = 0;
2107 	}
2108 	if (length>=16) {
2109 		auid = uid = get32bit(&data);
2110 		agid = gid = get32bit(&data);
2111 		sessions_ugid_remap(eptr->sesdata,&uid,&gid);
2112 	} else {
2113 		auid = uid = 12345;
2114 		agid = gid = 12345;
2115 	}
2116 	status = fs_getattr(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,opened,uid,gid,auid,agid,attr);
2117 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_GETATTR,(status!=MFS_STATUS_OK)?5:(eptr->asize+4));
2118 	put32bit(&ptr,msgid);
2119 	if (status!=MFS_STATUS_OK) {
2120 		put8bit(&ptr,status);
2121 	} else {
2122 		memcpy(ptr,attr,eptr->asize);
2123 	}
2124 	sessions_inc_stats(eptr->sesdata,1);
2125 }
2126 
matoclserv_fuse_setattr(matoclserventry * eptr,const uint8_t * data,uint32_t length)2127 void matoclserv_fuse_setattr(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
2128 	uint32_t inode,uid,gids,auid,agid;
2129 	uint32_t *gid;
2130 	uint32_t i;
2131 	uint8_t opened;
2132 	uint16_t setmask;
2133 	uint8_t attr[ATTR_RECORD_SIZE];
2134 	uint32_t msgid;
2135 	uint8_t *ptr;
2136 	uint8_t status;
2137 	uint8_t sugidclearmode;
2138 	uint16_t attrmode;
2139 	uint32_t attruid,attrgid,attratime,attrmtime;
2140 	uint32_t disables;
2141 	uint8_t winattr,basesize;
2142 
2143 	basesize = (eptr->version>=VERSION2INT(3,0,93))?38:37;
2144 	if (length!=35 && length!=36 && length<basesize) {
2145 		syslog(LOG_NOTICE,"CLTOMA_FUSE_SETATTR - wrong size (%"PRIu32"/35|36|37|37+N*4|38+N*4)",length);
2146 		eptr->mode = KILL;
2147 		return;
2148 	}
2149 	msgid = get32bit(&data);
2150 	inode = get32bit(&data);
2151 	if (length>=37) {
2152 		opened = get8bit(&data);
2153 	} else {
2154 		opened = 0;
2155 	}
2156 	auid = uid = get32bit(&data);
2157 	if (length<=37) {
2158 		gids = 1;
2159 		gid = matoclserv_gid_storage(gids);
2160 		agid = gid[0] = get32bit(&data);
2161 	} else {
2162 		gids = get32bit(&data);
2163 		if (length!=basesize+4*gids) {
2164 			syslog(LOG_NOTICE,"CLTOMA_FUSE_SETATTR - wrong size (%"PRIu32":gids=%"PRIu32")",length,gids);
2165 			eptr->mode = KILL;
2166 			return;
2167 		}
2168 		gid = matoclserv_gid_storage(gids);
2169 		for (i=0 ; i<gids ; i++) {
2170 			gid[i] = get32bit(&data);
2171 		}
2172 		agid = gid[0];
2173 	}
2174 	sessions_ugid_remap(eptr->sesdata,&uid,gid);
2175 	setmask = get8bit(&data);
2176 	attrmode = get16bit(&data);
2177 	attruid = get32bit(&data);
2178 	attrgid = get32bit(&data);
2179 	attratime = get32bit(&data);
2180 	attrmtime = get32bit(&data);
2181 	if (basesize==38) {
2182 		winattr = get8bit(&data);
2183 	} else {
2184 		winattr = 0;
2185 	}
2186 	if (length>=36) {
2187 		sugidclearmode = get8bit(&data);
2188 	} else {
2189 		sugidclearmode = SUGID_CLEAR_MODE_ALWAYS; // this is safest option
2190 	}
2191 	disables = sessions_get_disables(eptr->sesdata);
2192 	if (((disables&DISABLE_CHOWN) && (setmask&(SET_UID_FLAG|SET_GID_FLAG))) || ((disables&DISABLE_CHMOD) && (setmask&SET_MODE_FLAG))) {
2193 		status = MFS_ERROR_EPERM;
2194 	} else if (setmask&SET_WINATTR_FLAG && basesize==37) {
2195 		status = MFS_ERROR_EINVAL;
2196 	} else {
2197 		status = fs_setattr(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,opened,uid,gids,gid,auid,agid,setmask,attrmode,attruid,attrgid,attratime,attrmtime,winattr,sugidclearmode,attr);
2198 	}
2199 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_SETATTR,(status!=MFS_STATUS_OK)?5:(eptr->asize+4));
2200 	put32bit(&ptr,msgid);
2201 	if (status!=MFS_STATUS_OK) {
2202 		put8bit(&ptr,status);
2203 	} else {
2204 		memcpy(ptr,attr,eptr->asize);
2205 	}
2206 	sessions_inc_stats(eptr->sesdata,2);
2207 }
2208 
matoclserv_fuse_truncate(matoclserventry * eptr,const uint8_t * data,uint32_t length)2209 void matoclserv_fuse_truncate(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
2210 	uint32_t inode,uid,gids,auid,agid;
2211 	uint32_t *gid;
2212 	uint32_t i;
2213 	uint32_t msgid;
2214 	uint8_t flags;
2215 	uint64_t fleng;
2216 	if (length!=24 && length<25) {
2217 		syslog(LOG_NOTICE,"CLTOMA_FUSE_TRUNCATE - wrong size (%"PRIu32"/24|25+N*4)",length);
2218 		eptr->mode = KILL;
2219 		return;
2220 	}
2221 	flags = 0;
2222 	msgid = get32bit(&data);
2223 	inode = get32bit(&data);
2224 	if (length>=25) {
2225 		flags = get8bit(&data);
2226 	}
2227 	auid = uid = get32bit(&data);
2228 	if (length<=25) {
2229 		gids = 1;
2230 		gid = matoclserv_gid_storage(gids);
2231 		agid = gid[0] = get32bit(&data);
2232 		if (length==24) {
2233 			if (uid==0 && gid[0]!=0) {	// stupid "flags" patch for old clients
2234 				flags = TRUNCATE_FLAG_OPENED;
2235 			}
2236 		}
2237 		sessions_ugid_remap(eptr->sesdata,&uid,gid);
2238 	} else {
2239 		gids = get32bit(&data);
2240 		if (length!=25+4*gids) {
2241 			syslog(LOG_NOTICE,"CLTOMA_FUSE_TRUNCATE - wrong size (%"PRIu32":gids=%"PRIu32")",length,gids);
2242 			eptr->mode = KILL;
2243 			return;
2244 		}
2245 		gid = matoclserv_gid_storage(gids);
2246 		for (i=0 ; i<gids ; i++) {
2247 			gid[i] = get32bit(&data);
2248 		}
2249 		agid = gid[0];
2250 		sessions_ugid_remap(eptr->sesdata,&uid,gid);
2251 	}
2252 	fleng = get64bit(&data);
2253 	matoclserv_fuse_truncate_common(eptr,msgid,inode,flags,uid,gids,gid,auid,agid,fleng);
2254 }
2255 
matoclserv_fuse_readlink(matoclserventry * eptr,const uint8_t * data,uint32_t length)2256 void matoclserv_fuse_readlink(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
2257 	uint32_t inode;
2258 	uint32_t pleng;
2259 	uint8_t *path;
2260 	uint32_t msgid;
2261 	uint8_t *ptr;
2262 	uint8_t status;
2263 	if (length!=8) {
2264 		syslog(LOG_NOTICE,"CLTOMA_FUSE_READLINK - wrong size (%"PRIu32"/8)",length);
2265 		eptr->mode = KILL;
2266 		return;
2267 	}
2268 	msgid = get32bit(&data);
2269 	inode = get32bit(&data);
2270 	status = fs_readlink(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,&pleng,&path);
2271 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_READLINK,(status!=MFS_STATUS_OK)?5:8+pleng+1);
2272 	put32bit(&ptr,msgid);
2273 	if (status!=MFS_STATUS_OK) {
2274 		put8bit(&ptr,status);
2275 	} else {
2276 		put32bit(&ptr,pleng+1);
2277 		if (pleng>0) {
2278 			memcpy(ptr,path,pleng);
2279 		}
2280 		ptr[pleng]=0;
2281 	}
2282 	sessions_inc_stats(eptr->sesdata,7);
2283 }
2284 
matoclserv_fuse_symlink(matoclserventry * eptr,const uint8_t * data,uint32_t length)2285 void matoclserv_fuse_symlink(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
2286 	uint32_t inode;
2287 	uint8_t nleng;
2288 	const uint8_t *name,*path;
2289 	uint32_t uid,gids,auid,agid;
2290 	uint32_t *gid;
2291 	uint32_t i;
2292 	uint32_t pleng;
2293 	uint32_t newinode;
2294 	uint8_t attr[ATTR_RECORD_SIZE];
2295 	uint32_t msgid;
2296 	uint8_t status;
2297 	uint8_t *ptr;
2298 	if (length<21) {
2299 		syslog(LOG_NOTICE,"CLTOMA_FUSE_SYMLINK - wrong size (%"PRIu32")",length);
2300 		eptr->mode = KILL;
2301 		return;
2302 	}
2303 	msgid = get32bit(&data);
2304 	inode = get32bit(&data);
2305 	nleng = get8bit(&data);
2306 	if (length<21U+nleng) {
2307 		syslog(LOG_NOTICE,"CLTOMA_FUSE_SYMLINK - wrong size (%"PRIu32":nleng=%"PRIu8")",length,nleng);
2308 		eptr->mode = KILL;
2309 		return;
2310 	}
2311 	name = data;
2312 	data += nleng;
2313 	pleng = get32bit(&data);
2314 	if (length<21U+nleng+pleng) {
2315 		syslog(LOG_NOTICE,"CLTOMA_FUSE_SYMLINK - wrong size (%"PRIu32":nleng=%"PRIu8":pleng=%"PRIu32")",length,nleng,pleng);
2316 		eptr->mode = KILL;
2317 		return;
2318 	}
2319 	path = data;
2320 	data += pleng;
2321 	auid = uid = get32bit(&data);
2322 	if (length==21U+nleng+pleng) {
2323 		gids = 1;
2324 		gid = matoclserv_gid_storage(gids);
2325 		agid = gid[0] = get32bit(&data);
2326 	} else {
2327 		gids = get32bit(&data);
2328 		if (length!=21U+nleng+pleng+4*gids) {
2329 			syslog(LOG_NOTICE,"CLTOMA_FUSE_SYMLINK - wrong size (%"PRIu32":nleng=%"PRIu8":pleng=%"PRIu32":gids=%"PRIu32")",length,nleng,pleng,gids);
2330 			eptr->mode = KILL;
2331 			return;
2332 		}
2333 		gid = matoclserv_gid_storage(gids);
2334 		for (i=0 ; i<gids ; i++) {
2335 			gid[i] = get32bit(&data);
2336 		}
2337 		agid = gid[0];
2338 	}
2339 	sessions_ugid_remap(eptr->sesdata,&uid,gid);
2340 	while (pleng>0 && path[pleng-1]==0) {
2341 		pleng--;
2342 	}
2343 	if (sessions_get_disables(eptr->sesdata)&DISABLE_SYMLINK) {
2344 		status = MFS_ERROR_EPERM;
2345 	} else {
2346 		status = fs_symlink(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,nleng,name,pleng,path,uid,gids,gid,auid,agid,&newinode,attr);
2347 	}
2348 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_SYMLINK,(status!=MFS_STATUS_OK)?5:(eptr->asize+8));
2349 	put32bit(&ptr,msgid);
2350 	if (status!=MFS_STATUS_OK) {
2351 		put8bit(&ptr,status);
2352 	} else {
2353 		put32bit(&ptr,newinode);
2354 		memcpy(ptr,attr,eptr->asize);
2355 	}
2356 	sessions_inc_stats(eptr->sesdata,6);
2357 }
2358 
matoclserv_fuse_mknod(matoclserventry * eptr,const uint8_t * data,uint32_t length)2359 void matoclserv_fuse_mknod(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
2360 	uint32_t inode,uid,gids,auid,agid,rdev;
2361 	uint32_t *gid;
2362 	uint32_t i;
2363 	uint8_t nleng;
2364 	const uint8_t *name;
2365 	uint8_t type;
2366 	uint16_t mode,cumask;
2367 	uint32_t disables;
2368 	uint32_t newinode;
2369 	uint8_t attr[ATTR_RECORD_SIZE];
2370 	uint32_t msgid;
2371 	uint8_t *ptr;
2372 	uint8_t status;
2373 	if (length<24) {
2374 		syslog(LOG_NOTICE,"CLTOMA_FUSE_MKNOD - wrong size (%"PRIu32")",length);
2375 		eptr->mode = KILL;
2376 		return;
2377 	}
2378 	msgid = get32bit(&data);
2379 	inode = get32bit(&data);
2380 	nleng = get8bit(&data);
2381 	if (length!=24U+nleng && length<26U+nleng) {
2382 		syslog(LOG_NOTICE,"CLTOMA_FUSE_MKNOD - wrong size (%"PRIu32":nleng=%"PRIu8")",length,nleng);
2383 		eptr->mode = KILL;
2384 		return;
2385 	}
2386 	name = data;
2387 	data += nleng;
2388 	type = get8bit(&data);
2389 	mode = get16bit(&data);
2390 	if (length>=26U+nleng) {
2391 		cumask = get16bit(&data);
2392 	} else {
2393 		cumask = 0;
2394 	}
2395 	cumask |= sessions_get_umask(eptr->sesdata);
2396 	auid = uid = get32bit(&data);
2397 	if (length<=26U+nleng) {
2398 		gids = 1;
2399 		gid = matoclserv_gid_storage(gids);
2400 		agid = gid[0] = get32bit(&data);
2401 	} else {
2402 		gids = get32bit(&data);
2403 		if (length!=26U+nleng+4*gids) {
2404 			syslog(LOG_NOTICE,"CLTOMA_FUSE_MKNOD - wrong size (%"PRIu32":nleng=%"PRIu8":gids=%"PRIu32")",length,nleng,gids);
2405 			eptr->mode = KILL;
2406 			return;
2407 		}
2408 		gid = matoclserv_gid_storage(gids);
2409 		for (i=0 ; i<gids ; i++) {
2410 			gid[i] = get32bit(&data);
2411 		}
2412 		agid = gid[0];
2413 	}
2414 	sessions_ugid_remap(eptr->sesdata,&uid,gid);
2415 	rdev = get32bit(&data);
2416 	disables = sessions_get_disables(eptr->sesdata);
2417 	if (((disables&DISABLE_MKFIFO) && (type==TYPE_FIFO)) || ((disables&DISABLE_MKDEV) && (type==TYPE_BLOCKDEV || type==TYPE_CHARDEV)) || ((disables&DISABLE_MKSOCK) && (type==TYPE_SOCKET)) || ((disables&DISABLE_CREATE) && (type==TYPE_FILE))) {
2418 		status = MFS_ERROR_EPERM;
2419 	} else {
2420 		status = fs_mknod(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,nleng,name,type,mode,cumask,uid,gids,gid,auid,agid,rdev,&newinode,attr,NULL);
2421 	}
2422 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_MKNOD,(status!=MFS_STATUS_OK)?5:(eptr->asize+8));
2423 	put32bit(&ptr,msgid);
2424 	if (status!=MFS_STATUS_OK) {
2425 		put8bit(&ptr,status);
2426 	} else {
2427 		put32bit(&ptr,newinode);
2428 		memcpy(ptr,attr,eptr->asize);
2429 	}
2430 	sessions_inc_stats(eptr->sesdata,8);
2431 }
2432 
matoclserv_fuse_mkdir(matoclserventry * eptr,const uint8_t * data,uint32_t length)2433 void matoclserv_fuse_mkdir(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
2434 	uint32_t inode,uid,gids,auid,agid;
2435 	uint32_t *gid;
2436 	uint32_t i;
2437 	uint8_t nleng;
2438 	const uint8_t *name;
2439 	uint16_t mode,cumask;
2440 	uint32_t newinode;
2441 	uint8_t attr[ATTR_RECORD_SIZE];
2442 	uint32_t msgid;
2443 	uint8_t *ptr;
2444 	uint8_t status;
2445 	uint8_t copysgid;
2446 	if (length<19) {
2447 		syslog(LOG_NOTICE,"CLTOMA_FUSE_MKDIR - wrong size (%"PRIu32")",length);
2448 		eptr->mode = KILL;
2449 		return;
2450 	}
2451 	msgid = get32bit(&data);
2452 	inode = get32bit(&data);
2453 	nleng = get8bit(&data);
2454 	if (length!=19U+nleng && length!=20U+nleng && length<22U+nleng) {
2455 		syslog(LOG_NOTICE,"CLTOMA_FUSE_MKDIR - wrong size (%"PRIu32":nleng=%"PRIu8")",length,nleng);
2456 		eptr->mode = KILL;
2457 		return;
2458 	}
2459 	name = data;
2460 	data += nleng;
2461 	mode = get16bit(&data);
2462 	if (length>=22U+nleng) {
2463 		cumask = get16bit(&data);
2464 	} else {
2465 		cumask = 0;
2466 	}
2467 	cumask |= sessions_get_umask(eptr->sesdata);
2468 	auid = uid = get32bit(&data);
2469 	if (length<=22U+nleng) {
2470 		gids = 1;
2471 		gid = matoclserv_gid_storage(gids);
2472 		agid = gid[0] = get32bit(&data);
2473 	} else {
2474 		gids = get32bit(&data);
2475 		if (length!=22U+nleng+4*gids) {
2476 			syslog(LOG_NOTICE,"CLTOMA_FUSE_MKDIR - wrong size (%"PRIu32":nleng=%"PRIu8":gids=%"PRIu32")",length,nleng,gids);
2477 			eptr->mode = KILL;
2478 			return;
2479 		}
2480 		gid = matoclserv_gid_storage(gids);
2481 		for (i=0 ; i<gids ; i++) {
2482 			gid[i] = get32bit(&data);
2483 		}
2484 		agid = gid[0];
2485 	}
2486 	sessions_ugid_remap(eptr->sesdata,&uid,gid);
2487 	if (length>20U+nleng) {
2488 		copysgid = get8bit(&data);
2489 	} else {
2490 		copysgid = 0; // by default do not copy sgid bit
2491 	}
2492 	if (sessions_get_disables(eptr->sesdata)&DISABLE_MKDIR) {
2493 		status = MFS_ERROR_EPERM;
2494 	} else {
2495 		status = fs_mkdir(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,nleng,name,mode,cumask,uid,gids,gid,auid,agid,copysgid,&newinode,attr);
2496 	}
2497 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_MKDIR,(status!=MFS_STATUS_OK)?5:(eptr->asize+8));
2498 	put32bit(&ptr,msgid);
2499 	if (status!=MFS_STATUS_OK) {
2500 		put8bit(&ptr,status);
2501 	} else {
2502 		put32bit(&ptr,newinode);
2503 		memcpy(ptr,attr,eptr->asize);
2504 	}
2505 	sessions_inc_stats(eptr->sesdata,4);
2506 }
2507 
matoclserv_fuse_unlink(matoclserventry * eptr,const uint8_t * data,uint32_t length)2508 void matoclserv_fuse_unlink(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
2509 	uint32_t inode,uid,gids,uinode;
2510 	uint32_t *gid;
2511 	uint32_t i;
2512 	uint8_t nleng;
2513 	const uint8_t *name;
2514 	uint32_t msgid;
2515 	uint8_t *ptr;
2516 	uint8_t status;
2517 	if (length<17) {
2518 		syslog(LOG_NOTICE,"CLTOMA_FUSE_UNLINK - wrong size (%"PRIu32")",length);
2519 		eptr->mode = KILL;
2520 		return;
2521 	}
2522 	msgid = get32bit(&data);
2523 	inode = get32bit(&data);
2524 	nleng = get8bit(&data);
2525 	if (length<17U+nleng) {
2526 		syslog(LOG_NOTICE,"CLTOMA_FUSE_UNLINK - wrong size (%"PRIu32":nleng=%"PRIu8")",length,nleng);
2527 		eptr->mode = KILL;
2528 		return;
2529 	}
2530 	name = data;
2531 	data += nleng;
2532 	uid = get32bit(&data);
2533 	if (length==17U+nleng) {
2534 		gids = 1;
2535 		gid = matoclserv_gid_storage(gids);
2536 		gid[0] = get32bit(&data);
2537 	} else {
2538 		gids = get32bit(&data);
2539 		if (length!=17U+nleng+4*gids) {
2540 			syslog(LOG_NOTICE,"CLTOMA_FUSE_UNLINK - wrong size (%"PRIu32":nleng=%"PRIu8":gids=%"PRIu32")",length,nleng,gids);
2541 			eptr->mode = KILL;
2542 			return;
2543 		}
2544 		gid = matoclserv_gid_storage(gids);
2545 		for (i=0 ; i<gids ; i++) {
2546 			gid[i] = get32bit(&data);
2547 		}
2548 	}
2549 	sessions_ugid_remap(eptr->sesdata,&uid,gid);
2550 	if (sessions_get_disables(eptr->sesdata)&DISABLE_UNLINK) {
2551 		status = MFS_ERROR_EPERM;
2552 	} else {
2553 		status = fs_unlink(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,nleng,name,uid,gids,gid,&uinode);
2554 	}
2555 	if (((eptr->version>=VERSION2INT(3,0,107) && eptr->version<VERSION2INT(4,0,0)) || eptr->version>=VERSION2INT(4,18,0)) && status==MFS_STATUS_OK) {
2556 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_UNLINK,8);
2557 		put32bit(&ptr,msgid);
2558 		put32bit(&ptr,uinode);
2559 	} else {
2560 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_UNLINK,5);
2561 		put32bit(&ptr,msgid);
2562 		put8bit(&ptr,status);
2563 	}
2564 	sessions_inc_stats(eptr->sesdata,9);
2565 }
2566 
matoclserv_fuse_rmdir(matoclserventry * eptr,const uint8_t * data,uint32_t length)2567 void matoclserv_fuse_rmdir(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
2568 	uint32_t inode,uid,gids,uinode;
2569 	uint32_t *gid;
2570 	uint32_t i;
2571 	uint8_t nleng;
2572 	const uint8_t *name;
2573 	uint32_t msgid;
2574 	uint8_t *ptr;
2575 	uint8_t status;
2576 	if (length<17) {
2577 		syslog(LOG_NOTICE,"CLTOMA_FUSE_RMDIR - wrong size (%"PRIu32")",length);
2578 		eptr->mode = KILL;
2579 		return;
2580 	}
2581 	msgid = get32bit(&data);
2582 	inode = get32bit(&data);
2583 	nleng = get8bit(&data);
2584 	if (length<17U+nleng) {
2585 		syslog(LOG_NOTICE,"CLTOMA_FUSE_RMDIR - wrong size (%"PRIu32":nleng=%"PRIu8")",length,nleng);
2586 		eptr->mode = KILL;
2587 		return;
2588 	}
2589 	name = data;
2590 	data += nleng;
2591 	uid = get32bit(&data);
2592 	if (length==17U+nleng) {
2593 		gids = 1;
2594 		gid = matoclserv_gid_storage(gids);
2595 		gid[0] = get32bit(&data);
2596 	} else {
2597 		gids = get32bit(&data);
2598 		if (length!=17U+nleng+4*gids) {
2599 			syslog(LOG_NOTICE,"CLTOMA_FUSE_RMDIR - wrong size (%"PRIu32":nleng=%"PRIu8":gids=%"PRIu32")",length,nleng,gids);
2600 			eptr->mode = KILL;
2601 			return;
2602 		}
2603 		gid = matoclserv_gid_storage(gids);
2604 		for (i=0 ; i<gids ; i++) {
2605 			gid[i] = get32bit(&data);
2606 		}
2607 	}
2608 	sessions_ugid_remap(eptr->sesdata,&uid,gid);
2609 	if (sessions_get_disables(eptr->sesdata)&DISABLE_RMDIR) {
2610 		status = MFS_ERROR_EPERM;
2611 	} else {
2612 		status = fs_rmdir(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,nleng,name,uid,gids,gid,&uinode);
2613 	}
2614 	if (((eptr->version>=VERSION2INT(3,0,107) && eptr->version<VERSION2INT(4,0,0)) || eptr->version>=VERSION2INT(4,18,0)) && status==MFS_STATUS_OK) {
2615 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_RMDIR,8);
2616 		put32bit(&ptr,msgid);
2617 		put32bit(&ptr,uinode);
2618 	} else {
2619 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_RMDIR,5);
2620 		put32bit(&ptr,msgid);
2621 		put8bit(&ptr,status);
2622 	}
2623 	sessions_inc_stats(eptr->sesdata,5);
2624 }
2625 
matoclserv_fuse_rename(matoclserventry * eptr,const uint8_t * data,uint32_t length)2626 void matoclserv_fuse_rename(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
2627 	uint32_t inode,inode_src,inode_dst;
2628 	uint8_t nleng_src,nleng_dst;
2629 	const uint8_t *name_src,*name_dst;
2630 	uint32_t uid,gids,auid,agid;
2631 	uint32_t *gid;
2632 	uint32_t i;
2633 	uint32_t disables;
2634 	uint8_t attr[ATTR_RECORD_SIZE];
2635 	uint32_t msgid;
2636 	uint8_t status;
2637 	uint8_t *ptr;
2638 	if (length<22) {
2639 		syslog(LOG_NOTICE,"CLTOMA_FUSE_RENAME - wrong size (%"PRIu32")",length);
2640 		eptr->mode = KILL;
2641 		return;
2642 	}
2643 	msgid = get32bit(&data);
2644 	inode_src = get32bit(&data);
2645 	nleng_src = get8bit(&data);
2646 	if (length<22U+nleng_src) {
2647 		syslog(LOG_NOTICE,"CLTOMA_FUSE_RENAME - wrong size (%"PRIu32":nleng_src=%"PRIu8")",length,nleng_src);
2648 		eptr->mode = KILL;
2649 		return;
2650 	}
2651 	name_src = data;
2652 	data += nleng_src;
2653 	inode_dst = get32bit(&data);
2654 	nleng_dst = get8bit(&data);
2655 	if (length<22U+nleng_src+nleng_dst) {
2656 		syslog(LOG_NOTICE,"CLTOMA_FUSE_RENAME - wrong size (%"PRIu32":nleng_src=%"PRIu8":nleng_dst=%"PRIu8")",length,nleng_src,nleng_dst);
2657 		eptr->mode = KILL;
2658 		return;
2659 	}
2660 	name_dst = data;
2661 	data += nleng_dst;
2662 	auid = uid = get32bit(&data);
2663 	if (length==22U+nleng_src+nleng_dst) {
2664 		gids = 1;
2665 		gid = matoclserv_gid_storage(gids);
2666 		agid = gid[0] = get32bit(&data);
2667 	} else {
2668 		gids = get32bit(&data);
2669 		if (length!=22U+nleng_src+nleng_dst+4*gids) {
2670 			syslog(LOG_NOTICE,"CLTOMA_FUSE_RENAME - wrong size (%"PRIu32":nleng_src=%"PRIu8":nleng_dst=%"PRIu8":gids=%"PRIu32")",length,nleng_src,nleng_dst,gids);
2671 			eptr->mode = KILL;
2672 			return;
2673 		}
2674 		gid = matoclserv_gid_storage(gids);
2675 		for (i=0 ; i<gids ; i++) {
2676 			gid[i] = get32bit(&data);
2677 		}
2678 		agid = gid[0];
2679 	}
2680 	sessions_ugid_remap(eptr->sesdata,&uid,gid);
2681 	disables = sessions_get_disables(eptr->sesdata);
2682 	if ((disables&(DISABLE_RENAME|DISABLE_MOVE))==(DISABLE_RENAME|DISABLE_MOVE) || ((disables&DISABLE_RENAME) && (nleng_src!=nleng_dst || memcmp(name_src,name_dst,nleng_src)!=0)) || ((disables&DISABLE_MOVE) && inode_src!=inode_dst)) {
2683 		status = MFS_ERROR_EPERM;
2684 	} else {
2685 		status = fs_rename(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode_src,nleng_src,name_src,inode_dst,nleng_dst,name_dst,uid,gids,gid,auid,agid,((disables&DISABLE_UNLINK)?1:0)|((disables&DISABLE_RMDIR)?2:0),&inode,attr);
2686 	}
2687 	if (eptr->version>=VERSION2INT(1,6,21) && status==MFS_STATUS_OK) {
2688 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_RENAME,eptr->asize+8);
2689 	} else {
2690 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_RENAME,5);
2691 	}
2692 	put32bit(&ptr,msgid);
2693 	if (eptr->version>=VERSION2INT(1,6,21) && status==MFS_STATUS_OK) {
2694 		put32bit(&ptr,inode);
2695 		memcpy(ptr,attr,eptr->asize);
2696 	} else {
2697 		put8bit(&ptr,status);
2698 	}
2699 	sessions_inc_stats(eptr->sesdata,10);
2700 }
2701 
matoclserv_fuse_link(matoclserventry * eptr,const uint8_t * data,uint32_t length)2702 void matoclserv_fuse_link(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
2703 	uint32_t inode,inode_dst;
2704 	uint8_t nleng_dst;
2705 	const uint8_t *name_dst;
2706 	uint32_t uid,gids,auid,agid;
2707 	uint32_t *gid;
2708 	uint32_t i;
2709 	uint32_t newinode;
2710 	uint8_t attr[ATTR_RECORD_SIZE];
2711 	uint32_t msgid;
2712 	uint8_t *ptr;
2713 	uint8_t status;
2714 	if (length<21) {
2715 		syslog(LOG_NOTICE,"CLTOMA_FUSE_LINK - wrong size (%"PRIu32")",length);
2716 		eptr->mode = KILL;
2717 		return;
2718 	}
2719 	msgid = get32bit(&data);
2720 	inode = get32bit(&data);
2721 	inode_dst = get32bit(&data);
2722 	nleng_dst = get8bit(&data);
2723 	if (length<21U+nleng_dst) {
2724 		syslog(LOG_NOTICE,"CLTOMA_FUSE_LINK - wrong size (%"PRIu32":nleng_dst=%"PRIu8")",length,nleng_dst);
2725 		eptr->mode = KILL;
2726 		return;
2727 	}
2728 	name_dst = data;
2729 	data += nleng_dst;
2730 	auid = uid = get32bit(&data);
2731 	if (length==21U+nleng_dst) {
2732 		gids = 1;
2733 		gid = matoclserv_gid_storage(gids);
2734 		agid = gid[0] = get32bit(&data);
2735 	} else {
2736 		gids = get32bit(&data);
2737 		if (length!=21U+nleng_dst+4*gids) {
2738 			syslog(LOG_NOTICE,"CLTOMA_FUSE_LINK - wrong size (%"PRIu32":nleng_dst=%"PRIu8":gids=%"PRIu32")",length,nleng_dst,gids);
2739 			eptr->mode = KILL;
2740 			return;
2741 		}
2742 		gid = matoclserv_gid_storage(gids);
2743 		for (i=0 ; i<gids ; i++) {
2744 			gid[i] = get32bit(&data);
2745 		}
2746 		agid = gid[0];
2747 	}
2748 	sessions_ugid_remap(eptr->sesdata,&uid,gid);
2749 	if (sessions_get_disables(eptr->sesdata)&DISABLE_LINK) {
2750 		status = MFS_ERROR_EPERM;
2751 	} else {
2752 		status = fs_link(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,inode_dst,nleng_dst,name_dst,uid,gids,gid,auid,agid,&newinode,attr);
2753 	}
2754 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_LINK,(status!=MFS_STATUS_OK)?5:(eptr->asize+8));
2755 	put32bit(&ptr,msgid);
2756 	if (status!=MFS_STATUS_OK) {
2757 		put8bit(&ptr,status);
2758 	} else {
2759 		put32bit(&ptr,newinode);
2760 		memcpy(ptr,attr,eptr->asize);
2761 	}
2762 	sessions_inc_stats(eptr->sesdata,11);
2763 }
2764 
matoclserv_fuse_readdir(matoclserventry * eptr,const uint8_t * data,uint32_t length)2765 void matoclserv_fuse_readdir(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
2766 	uint32_t inode,uid,gids,auid,agid;
2767 	uint32_t *gid;
2768 	uint32_t i;
2769 	uint8_t flags;
2770 	uint32_t msgid;
2771 	uint8_t *ptr;
2772 	uint8_t status;
2773 	uint32_t dleng;
2774 	uint32_t maxentries;
2775 	uint64_t nedgeid;
2776 	uint8_t attrmode;
2777 	void *c1,*c2;
2778 
2779 	if (eptr->asize==35) {
2780 		attrmode = 1;
2781 	} else if (eptr->asize==ATTR_RECORD_SIZE) {
2782 		attrmode = 2;
2783 	} else {
2784 		syslog(LOG_NOTICE,"CLTOMA_FUSE_READDIR - requested attr size not implemented");
2785 		eptr->mode = KILL;
2786 		return;
2787 	}
2788 	if (length!=16 && length!=17 && length<29) {
2789 		syslog(LOG_NOTICE,"CLTOMA_FUSE_READDIR - wrong size (%"PRIu32"/16|17|29+N*4)",length);
2790 		eptr->mode = KILL;
2791 		return;
2792 	}
2793 	msgid = get32bit(&data);
2794 	inode = get32bit(&data);
2795 	auid = uid = get32bit(&data);
2796 	if (length<=29) {
2797 		gids = 1;
2798 		gid = matoclserv_gid_storage(gids);
2799 		agid = gid[0] = get32bit(&data);
2800 	} else {
2801 		gids = get32bit(&data);
2802 		if (length!=29+4*gids) {
2803 			syslog(LOG_NOTICE,"CLTOMA_FUSE_READDIR - wrong size (%"PRIu32":gids=%"PRIu32")",length,gids);
2804 			eptr->mode = KILL;
2805 			return;
2806 		}
2807 		gid = matoclserv_gid_storage(gids);
2808 		for (i=0 ; i<gids ; i++) {
2809 			gid[i] = get32bit(&data);
2810 		}
2811 		agid = gid[0];
2812 	}
2813 	sessions_ugid_remap(eptr->sesdata,&uid,gid);
2814 	if (length>=17) {
2815 		flags = get8bit(&data);
2816 	} else {
2817 		flags = 0;
2818 	}
2819 	if (length>=29) {
2820 		maxentries = get32bit(&data);
2821 		nedgeid = get64bit(&data);
2822 	} else {
2823 		maxentries = 0xFFFFFFFF;
2824 		nedgeid = 0;
2825 	}
2826 	if (sessions_get_disables(eptr->sesdata)&DISABLE_READDIR) {
2827 		status = MFS_ERROR_EPERM;
2828 	} else {
2829 		status = fs_readdir_size(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,uid,gids,gid,flags,maxentries,nedgeid,&c1,&c2,&dleng,attrmode);
2830 	}
2831 	if (status!=MFS_STATUS_OK) {
2832 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_READDIR,5);
2833 	} else if (length>=29) {
2834 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_READDIR,12+dleng);
2835 	} else {
2836 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_READDIR,4+dleng);
2837 	}
2838 	put32bit(&ptr,msgid);
2839 	if (status!=MFS_STATUS_OK) {
2840 		put8bit(&ptr,status);
2841 	} else {
2842 		if (length>=29) {
2843 			put64bit(&ptr,nedgeid);
2844 		}
2845 		fs_readdir_data(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),uid,gid[0],auid,agid,flags,maxentries,&nedgeid,c1,c2,ptr,attrmode);
2846 	}
2847 	sessions_inc_stats(eptr->sesdata,12);
2848 }
2849 
matoclserv_fuse_open(matoclserventry * eptr,const uint8_t * data,uint32_t length)2850 void matoclserv_fuse_open(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
2851 	uint32_t inode,uid,gids,auid,agid;
2852 	uint32_t *gid;
2853 	uint32_t i;
2854 	uint8_t flags;
2855 	uint8_t oflags;
2856 	uint8_t sesflags;
2857 	uint8_t attr[ATTR_RECORD_SIZE];
2858 	uint32_t msgid;
2859 	uint8_t *ptr;
2860 	uint8_t status;
2861 	if (length<17) {
2862 		syslog(LOG_NOTICE,"CLTOMA_FUSE_OPEN - wrong size (%"PRIu32"/17+N*4)",length);
2863 		eptr->mode = KILL;
2864 		return;
2865 	}
2866 	msgid = get32bit(&data);
2867 	inode = get32bit(&data);
2868 	if (length==17) {
2869 		gids = 1;
2870 		gid = matoclserv_gid_storage(gids);
2871 		auid = uid = get32bit(&data);
2872 		agid = gid[0] = get32bit(&data);
2873 		sessions_ugid_remap(eptr->sesdata,&uid,gid);
2874 	} else {
2875 		auid = uid = get32bit(&data);
2876 		gids = get32bit(&data);
2877 		if (length!=17+gids*4) {
2878 			syslog(LOG_NOTICE,"CLTOMA_FUSE_OPEN - wrong size (%"PRIu32":gids=%"PRIu32")",length,gids);
2879 			eptr->mode = KILL;
2880 			return;
2881 		}
2882 		gid = matoclserv_gid_storage(gids);
2883 		for (i=0 ; i<gids ; i++) {
2884 			gid[i] = get32bit(&data);
2885 		}
2886 		agid = gid[0];
2887 		sessions_ugid_remap(eptr->sesdata,&uid,gid);
2888 	}
2889 	flags = get8bit(&data);
2890 	oflags = 0;
2891 	sesflags = sessions_get_sesflags(eptr->sesdata);
2892 	if ((flags&OPEN_TRUNCATE) && sessions_get_disables(eptr->sesdata)&DISABLE_TRUNCATE) {
2893 		status = MFS_ERROR_EPERM;
2894 	} else {
2895 		status = fs_opencheck(sessions_get_rootinode(eptr->sesdata),sesflags,inode,uid,gids,gid,auid,agid,flags,attr,&oflags);
2896 	}
2897 	if (status==MFS_STATUS_OK && eptr->version<VERSION2INT(3,0,113) && (oflags&OPEN_APPENDONLY) && (flags&OPEN_WRITE)) {
2898 		// this mount doesn't support append only, so we should deny access to any write
2899 		status=MFS_ERROR_EACCES;
2900 	}
2901 	if (status==MFS_STATUS_OK) {
2902 		of_openfile(sessions_get_id(eptr->sesdata),inode);
2903 		if (flags&OPEN_CACHE_CLEARED) {
2904 			dcm_access(inode,sessions_get_id(eptr->sesdata));
2905 		}
2906 	}
2907 	if (eptr->version>=VERSION2INT(1,6,9) && status==MFS_STATUS_OK) {
2908 		if (eptr->version>=VERSION2INT(3,0,113)) {
2909 			if ((oflags&OPEN_DIRECTMODE)==0) {
2910 				if (dcm_open(inode,sessions_get_id(eptr->sesdata))) {
2911 					oflags |= OPEN_KEEPCACHE;
2912 				} else { // just fix for old clients
2913 					if (sesflags&SESFLAG_ATTRBIT) {
2914 						attr[0]&=(0xFF^MATTR_ALLOWDATACACHE);
2915 					} else {
2916 						attr[1]&=(0xFF^(MATTR_ALLOWDATACACHE<<4));
2917 					}
2918 				}
2919 			}
2920 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_OPEN,(eptr->asize+5));
2921 			put32bit(&ptr,msgid);
2922 			put8bit(&ptr,oflags);
2923 			memcpy(ptr,attr,eptr->asize);
2924 		} else {
2925 			if ((sesflags&SESFLAG_ATTRBIT)==0 || (attr[0]&MATTR_DIRECTMODE)==0) {
2926 				if (dcm_open(inode,sessions_get_id(eptr->sesdata))==0) {
2927 					if (sesflags&SESFLAG_ATTRBIT) {
2928 						attr[0]&=(0xFF^MATTR_ALLOWDATACACHE);
2929 					} else {
2930 						attr[1]&=(0xFF^(MATTR_ALLOWDATACACHE<<4));
2931 					}
2932 				}
2933 			}
2934 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_OPEN,(eptr->asize+4));
2935 			put32bit(&ptr,msgid);
2936 			memcpy(ptr,attr,eptr->asize);
2937 		}
2938 	} else {
2939 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_OPEN,5);
2940 		put32bit(&ptr,msgid);
2941 		put8bit(&ptr,status);
2942 	}
2943 	sessions_inc_stats(eptr->sesdata,13);
2944 }
2945 
matoclserv_fuse_create(matoclserventry * eptr,const uint8_t * data,uint32_t length)2946 void matoclserv_fuse_create(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
2947 	uint32_t inode,uid,gids,auid,agid;
2948 	uint32_t *gid;
2949 	uint32_t i;
2950 	uint8_t nleng;
2951 	const uint8_t *name;
2952 	uint16_t mode,cumask;
2953 	uint32_t newinode;
2954 	uint8_t attr[ATTR_RECORD_SIZE];
2955 	uint32_t msgid;
2956 	uint8_t *ptr;
2957 	uint8_t status;
2958 	uint8_t oflags;
2959 	uint8_t sesflags;
2960 	if (length<19) {
2961 		syslog(LOG_NOTICE,"CLTOMA_FUSE_CREATE - wrong size (%"PRIu32")",length);
2962 		eptr->mode = KILL;
2963 		return;
2964 	}
2965 	msgid = get32bit(&data);
2966 	inode = get32bit(&data);
2967 	nleng = get8bit(&data);
2968 	if (length!=19U+nleng && length<21U+nleng) {
2969 		syslog(LOG_NOTICE,"CLTOMA_FUSE_CREATE - wrong size (%"PRIu32":nleng=%"PRIu8")",length,nleng);
2970 		eptr->mode = KILL;
2971 		return;
2972 	}
2973 	name = data;
2974 	data += nleng;
2975 	mode = get16bit(&data);
2976 	if (length>=21U+nleng) {
2977 		cumask = get16bit(&data);
2978 	} else {
2979 		cumask = 0;
2980 	}
2981 	cumask |= sessions_get_umask(eptr->sesdata);
2982 	auid = uid = get32bit(&data);
2983 	if (length<=21U+nleng) {
2984 		gids = 1;
2985 		gid = matoclserv_gid_storage(gids);
2986 		agid = gid[0] = get32bit(&data);
2987 	} else {
2988 		gids = get32bit(&data);
2989 		if (length!=21U+nleng+4*gids) {
2990 			syslog(LOG_NOTICE,"CLTOMA_FUSE_CREATE - wrong size (%"PRIu32":nleng=%"PRIu8":gids=%"PRIu32")",length,nleng,gids);
2991 			eptr->mode = KILL;
2992 			return;
2993 		}
2994 		gid = matoclserv_gid_storage(gids);
2995 		for (i=0 ; i<gids ; i++) {
2996 			gid[i] = get32bit(&data);
2997 		}
2998 		agid = gid[0];
2999 	}
3000 	sessions_ugid_remap(eptr->sesdata,&uid,gid);
3001 	sesflags = sessions_get_sesflags(eptr->sesdata);
3002 	if (sessions_get_disables(eptr->sesdata)&DISABLE_CREATE) {
3003 		status = MFS_ERROR_EPERM;
3004 	} else {
3005 		status = fs_mknod(sessions_get_rootinode(eptr->sesdata),sesflags,inode,nleng,name,TYPE_FILE,mode,cumask,uid,gids,gid,auid,agid,0,&newinode,attr,&oflags);
3006 	}
3007 	if (status==MFS_STATUS_OK) {
3008 		if (CreateFirstChunk) {
3009 			uint64_t prevchunkid,chunkid,fleng;
3010 			uint8_t opflag;
3011 			swchunks *swc;
3012 			/* create first chunk */
3013 			if (fs_writechunk(newinode,0,0,&prevchunkid,&chunkid,&fleng,&opflag,eptr->peerip)==MFS_STATUS_OK) {
3014 				massert(prevchunkid==0,"chunk created after mknod - prevchunkid should be always zero");
3015 				if (opflag) {
3016 					i = CHUNKHASH(chunkid);
3017 					swc = malloc(sizeof(swchunks));
3018 					passert(swc);
3019 					swc->eptr = eptr;
3020 					swc->inode = newinode;
3021 					swc->indx = 0;
3022 					swc->prevchunkid = prevchunkid;
3023 					swc->chunkid = chunkid;
3024 					swc->msgid = 0;
3025 					swc->fleng = fleng;
3026 					swc->type = FUSE_CREATE;
3027 					swc->next = swchunkshash[i];
3028 					swchunkshash[i] = swc;
3029 				} else {
3030 					fs_writeend(newinode,0,chunkid,0,NULL); // no operation? - just unlock this chunk
3031 				}
3032 			}
3033 		}
3034 		/* open file */
3035 		of_openfile(sessions_get_id(eptr->sesdata),newinode);
3036 		if (eptr->version>=VERSION2INT(3,0,113)) {
3037 			if ((oflags&OPEN_DIRECTMODE)==0) {
3038 // testing dcm_open doesn't make sense here - this is new inode
3039 //				if (dcm_open(newinode,sessions_get_id(eptr->sesdata))) {
3040 //					oflags |= OPEN_KEEPCACHE;
3041 //				} else { // just fix for old clients
3042 					if (sesflags&SESFLAG_ATTRBIT) {
3043 						attr[0]&=(0xFF^MATTR_ALLOWDATACACHE);
3044 					} else {
3045 						attr[1]&=(0xFF^(MATTR_ALLOWDATACACHE<<4));
3046 					}
3047 //				}
3048 			}
3049 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_CREATE,eptr->asize+9);
3050 			put32bit(&ptr,msgid);
3051 			put8bit(&ptr,oflags);
3052 			put32bit(&ptr,newinode);
3053 			memcpy(ptr,attr,eptr->asize);
3054 		} else {
3055 			if ((sesflags&SESFLAG_ATTRBIT)==0 || (attr[0]&MATTR_DIRECTMODE)==0) {
3056 //				if (dcm_open(newinode,sessions_get_id(eptr->sesdata))==0) {
3057 					if (sesflags&SESFLAG_ATTRBIT) {
3058 						attr[0]&=(0xFF^MATTR_ALLOWDATACACHE);
3059 					} else {
3060 						attr[1]&=(0xFF^(MATTR_ALLOWDATACACHE<<4));
3061 					}
3062 //				}
3063 			}
3064 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_CREATE,eptr->asize+8);
3065 			put32bit(&ptr,msgid);
3066 			put32bit(&ptr,newinode);
3067 			memcpy(ptr,attr,eptr->asize);
3068 		}
3069 	} else {
3070 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_CREATE,5);
3071 		put32bit(&ptr,msgid);
3072 		put8bit(&ptr,status);
3073 	}
3074 	sessions_inc_stats(eptr->sesdata,8);
3075 	sessions_inc_stats(eptr->sesdata,13);
3076 }
3077 
matoclserv_fuse_read_chunk(matoclserventry * eptr,const uint8_t * data,uint32_t length)3078 void matoclserv_fuse_read_chunk(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
3079 	uint32_t inode;
3080 	uint32_t indx;
3081 	uint8_t chunkopflags;
3082 	uint32_t msgid;
3083 
3084 	if (length!=12 && length!=13) {
3085 		syslog(LOG_NOTICE,"CLTOMA_FUSE_READ_CHUNK - wrong size (%"PRIu32"/12|13)",length);
3086 		eptr->mode = KILL;
3087 		return;
3088 	}
3089 	msgid = get32bit(&data);
3090 	inode = get32bit(&data);
3091 	indx = get32bit(&data);
3092 	if (length==13) {
3093 		chunkopflags = get8bit(&data);
3094 	} else {
3095 		chunkopflags = CHUNKOPFLAG_CANMODTIME;
3096 	}
3097 	if (eptr->version>=VERSION2INT(3,0,74)) {
3098 		chunkopflags &= ~CHUNKOPFLAG_CANMODTIME;
3099 	}
3100 	matoclserv_fuse_read_chunk_common(eptr,msgid,inode,indx,chunkopflags);
3101 }
3102 
matoclserv_fuse_write_chunk(matoclserventry * eptr,const uint8_t * data,uint32_t length)3103 void matoclserv_fuse_write_chunk(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
3104 	uint32_t inode;
3105 	uint32_t indx;
3106 	uint32_t msgid;
3107 	uint8_t chunkopflags;
3108 
3109 	if (length!=12 && length!=13) {
3110 		syslog(LOG_NOTICE,"CLTOMA_FUSE_WRITE_CHUNK - wrong size (%"PRIu32"/12|13)",length);
3111 		eptr->mode = KILL;
3112 		return;
3113 	}
3114 	msgid = get32bit(&data);
3115 	inode = get32bit(&data);
3116 	indx = get32bit(&data);
3117 	if (length>=13) {
3118 		chunkopflags = get8bit(&data);
3119 	} else {
3120 		chunkopflags = CHUNKOPFLAG_CANMODTIME;
3121 	}
3122 	if (eptr->version>=VERSION2INT(3,0,74)) {
3123 		chunkopflags &= ~CHUNKOPFLAG_CANMODTIME;
3124 	}
3125 	matoclserv_fuse_write_chunk_common(eptr,msgid,inode,indx,chunkopflags);
3126 }
3127 
matoclserv_fuse_write_chunk_end(matoclserventry * eptr,const uint8_t * data,uint32_t length)3128 void matoclserv_fuse_write_chunk_end(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
3129 	uint8_t *ptr;
3130 	uint32_t msgid;
3131 	uint32_t inode;
3132 	uint64_t fleng;
3133 	uint32_t indx;
3134 	uint32_t version;
3135 	uint64_t chunkid;
3136 	uint8_t status;
3137 	uint8_t chunkopflags;
3138 	uint8_t flenghaschanged;
3139 //	chunklist *cl,**acl;
3140 	if (length!=24 && length!=25 && length!=29) {
3141 		syslog(LOG_NOTICE,"CLTOMA_FUSE_WRITE_CHUNK_END - wrong size (%"PRIu32"/24|25|29)",length);
3142 		eptr->mode = KILL;
3143 		return;
3144 	}
3145 	msgid = get32bit(&data);
3146 	chunkid = get64bit(&data);
3147 	inode = get32bit(&data);
3148 	if (length>=29) {
3149 		indx = get32bit(&data);
3150 	} else {
3151 		indx = 0;
3152 	}
3153 	fleng = get64bit(&data);
3154 	if (length>=25) {
3155 		chunkopflags = get8bit(&data);
3156 	} else {
3157 		chunkopflags = CHUNKOPFLAG_CANMODTIME;
3158 	}
3159 	if (eptr->version>=VERSION2INT(3,0,74)) {
3160 		chunkopflags &= ~CHUNKOPFLAG_CANMODTIME;
3161 	}
3162 	flenghaschanged = 0;
3163 	if (sessions_get_disables(eptr->sesdata)&DISABLE_WRITE) {
3164 		status = MFS_ERROR_EPERM;
3165 	} else if (sessions_get_sesflags(eptr->sesdata)&SESFLAG_READONLY) {
3166 		if (eptr->version>=VERSION2INT(3,0,101)) {
3167 			status = MFS_ERROR_EROFS;
3168 		} else {
3169 			status = MFS_ERROR_IO;
3170 		}
3171 	} else {
3172 		status = fs_writeend(inode,fleng,chunkid,chunkopflags,&flenghaschanged);
3173 	}
3174 	dcm_modify(inode,sessions_get_id(eptr->sesdata));
3175 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_WRITE_CHUNK_END,5);
3176 	put32bit(&ptr,msgid);
3177 	put8bit(&ptr,status);
3178 	if (length==29) {
3179 		chunk_get_version(chunkid,&version);
3180 		matoclserv_fuse_chunk_has_changed(eptr,inode,indx,chunkid,version,fleng,0);
3181 	} else if (flenghaschanged) {
3182 		matoclserv_fuse_fleng_has_changed(eptr,inode,fleng);
3183 	}
3184 }
3185 
matoclserv_fuse_chunk_has_changed(matoclserventry * eptr,uint32_t inode,uint32_t chindx,uint64_t chunkid,uint32_t version,uint64_t fleng,uint8_t truncateflag)3186 void matoclserv_fuse_chunk_has_changed(matoclserventry *eptr,uint32_t inode,uint32_t chindx,uint64_t chunkid,uint32_t version,uint64_t fleng,uint8_t truncateflag) {
3187 	matoclserventry *xeptr;
3188 	uint8_t *ptr;
3189 	for (xeptr=matoclservhead ; xeptr ; xeptr=xeptr->next) {
3190 		if (xeptr!=eptr && xeptr->mode==DATA && xeptr->registered==1 && xeptr->sesdata!=NULL && xeptr->version>=VERSION2INT(3,0,74)) {
3191 			if (of_isfileopened_by_session(inode,sessions_get_id(xeptr->sesdata))) {
3192 				ptr = matoclserv_createpacket(xeptr,MATOCL_FUSE_CHUNK_HAS_CHANGED,33);
3193 				put32bit(&ptr,0);
3194 				put32bit(&ptr,inode);
3195 				put32bit(&ptr,chindx);
3196 				put64bit(&ptr,chunkid);
3197 				put32bit(&ptr,version);
3198 				put64bit(&ptr,fleng);
3199 				put8bit(&ptr,truncateflag);
3200 			}
3201 		}
3202 	}
3203 }
3204 
matoclserv_fuse_fleng_has_changed(matoclserventry * eptr,uint32_t inode,uint64_t fleng)3205 void matoclserv_fuse_fleng_has_changed(matoclserventry *eptr,uint32_t inode,uint64_t fleng) {
3206 	matoclserventry *xeptr;
3207 	uint8_t *ptr;
3208 	for (xeptr=matoclservhead ; xeptr ; xeptr=xeptr->next) {
3209 		if (xeptr!=eptr && xeptr->mode==DATA && xeptr->registered==1 && xeptr->sesdata!=NULL && xeptr->version>=VERSION2INT(3,0,74)) {
3210 			if (of_isfileopened_by_session(inode,sessions_get_id(xeptr->sesdata))) {
3211 				ptr = matoclserv_createpacket(xeptr,MATOCL_FUSE_FLENG_HAS_CHANGED,16);
3212 				put32bit(&ptr,0);
3213 				put32bit(&ptr,inode);
3214 				put64bit(&ptr,fleng);
3215 			}
3216 		}
3217 	}
3218 }
3219 
matoclserv_fuse_invalidate_chunk_cache(void)3220 void matoclserv_fuse_invalidate_chunk_cache(void) {
3221 	matoclserventry *xeptr;
3222 	uint8_t *ptr;
3223 	for (xeptr=matoclservhead ; xeptr ; xeptr=xeptr->next) {
3224 		if (xeptr->mode==DATA && xeptr->registered==1 && xeptr->sesdata!=NULL && (xeptr->version>=VERSION2INT(4,3,0) || (xeptr->version>=VERSION2INT(3,0,100) && xeptr->version<VERSION2INT(4,0,0)))) {
3225 			ptr = matoclserv_createpacket(xeptr,MATOCL_FUSE_INVALIDATE_CHUNK_CACHE,4);
3226 			put32bit(&ptr,0);
3227 		}
3228 	}
3229 }
3230 
matoclserv_find_connection(uint32_t sessionid)3231 static inline matoclserventry* matoclserv_find_connection(uint32_t sessionid) {
3232 	matoclserventry *eptr;
3233 	for (eptr=matoclservhead ; eptr ; eptr=eptr->next) {
3234 		if (eptr->mode==DATA && eptr->registered==1 && eptr->sesdata!=NULL) {
3235 			if (sessions_get_id(eptr->sesdata)==sessionid) {
3236 				return eptr;
3237 			}
3238 		}
3239 	}
3240 	return NULL;
3241 }
3242 
matoclserv_fuse_flock_wake_up(uint32_t sessionid,uint32_t msgid,uint8_t status)3243 void matoclserv_fuse_flock_wake_up(uint32_t sessionid,uint32_t msgid,uint8_t status) {
3244 	matoclserventry *eptr;
3245 	uint8_t *ptr;
3246 	eptr = matoclserv_find_connection(sessionid);
3247 	if (eptr==NULL) {
3248 		return;
3249 	}
3250 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_FLOCK,5);
3251 	put32bit(&ptr,msgid);
3252 	put8bit(&ptr,status);
3253 }
3254 
matoclserv_fuse_flock(matoclserventry * eptr,const uint8_t * data,uint32_t length)3255 void matoclserv_fuse_flock(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
3256 	uint32_t msgid;
3257 	uint32_t inode;
3258 	uint32_t reqid;
3259 	uint64_t owner;
3260 	uint8_t cmd;
3261 	uint8_t *ptr;
3262 	uint8_t status;
3263 	if (length!=21) {
3264 		syslog(LOG_NOTICE,"CLTOMA_FUSE_FLOCK - wrong size (%"PRIu32"/21)",length);
3265 		eptr->mode = KILL;
3266 		return;
3267 	}
3268 	msgid = get32bit(&data);
3269 	inode = get32bit(&data);
3270 	reqid = get32bit(&data);
3271 	owner = get64bit(&data);
3272 	cmd = get8bit(&data);
3273 	status = flock_locks_cmd(sessions_get_id(eptr->sesdata),msgid,reqid,inode,owner,cmd);
3274 	if (status==MFS_ERROR_WAITING) {
3275 		return;
3276 	}
3277 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_FLOCK,5);
3278 	put32bit(&ptr,msgid);
3279 	put8bit(&ptr,status);
3280 }
3281 
matoclserv_fuse_posix_lock_wake_up(uint32_t sessionid,uint32_t msgid,uint8_t status)3282 void matoclserv_fuse_posix_lock_wake_up(uint32_t sessionid,uint32_t msgid,uint8_t status) {
3283 	matoclserventry *eptr;
3284 	uint8_t *ptr;
3285 	eptr = matoclserv_find_connection(sessionid);
3286 	if (eptr==NULL) {
3287 		return;
3288 	}
3289 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_POSIX_LOCK,5);
3290 	put32bit(&ptr,msgid);
3291 	put8bit(&ptr,status);
3292 }
3293 
matoclserv_fuse_posix_lock(matoclserventry * eptr,const uint8_t * data,uint32_t length)3294 void matoclserv_fuse_posix_lock(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
3295 	uint32_t msgid;
3296 	uint32_t inode;
3297 	uint32_t reqid;
3298 	uint32_t pid;
3299 	uint64_t owner;
3300 	uint64_t start,end;
3301 	uint8_t cmd,type;
3302 	uint8_t *ptr;
3303 	uint8_t status;
3304 	if (length!=42) {
3305 		syslog(LOG_NOTICE,"CLTOMA_FUSE_POSIX_LOCK - wrong size (%"PRIu32"/42)",length);
3306 		eptr->mode = KILL;
3307 		return;
3308 	}
3309 	msgid = get32bit(&data);
3310 	inode = get32bit(&data);
3311 	reqid = get32bit(&data);
3312 	owner = get64bit(&data);
3313 	pid = get32bit(&data);
3314 	cmd = get8bit(&data);
3315 	type = get8bit(&data);
3316 	start = get64bit(&data);
3317 	end = get64bit(&data);
3318 	status = posix_lock_cmd(sessions_get_id(eptr->sesdata),msgid,reqid,inode,owner,cmd,&type,&start,&end,&pid);
3319 	if (status==MFS_ERROR_WAITING) {
3320 		return;
3321 	}
3322 	if (cmd==POSIX_LOCK_CMD_GET && status==MFS_STATUS_OK) {
3323 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_POSIX_LOCK,25);
3324 		put32bit(&ptr,msgid);
3325 		put32bit(&ptr,pid);
3326 		put8bit(&ptr,type);
3327 		put64bit(&ptr,start);
3328 		put64bit(&ptr,end);
3329 	} else {
3330 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_POSIX_LOCK,5);
3331 		put32bit(&ptr,msgid);
3332 		put8bit(&ptr,status);
3333 	}
3334 }
3335 
matoclserv_fuse_repair(matoclserventry * eptr,const uint8_t * data,uint32_t length)3336 void matoclserv_fuse_repair(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
3337 	uint32_t inode,uid,gids;
3338 	uint32_t *gid;
3339 	uint32_t i;
3340 	uint32_t msgid;
3341 	uint32_t chunksnotchanged,chunkserased,chunksrepaired;
3342 	uint8_t *ptr;
3343 	uint8_t status;
3344 	if (length<16) {
3345 		syslog(LOG_NOTICE,"CLTOMA_FUSE_REPAIR - wrong size (%"PRIu32"/16+N*4)",length);
3346 		eptr->mode = KILL;
3347 		return;
3348 	}
3349 	msgid = get32bit(&data);
3350 	inode = get32bit(&data);
3351 	uid = get32bit(&data);
3352 	if (length==16) {
3353 		gids = 1;
3354 		gid = matoclserv_gid_storage(gids);
3355 		gid[0] = get32bit(&data);
3356 	} else {
3357 		gids = get32bit(&data);
3358 		if (length!=16+4*gids) {
3359 			syslog(LOG_NOTICE,"CLTOMA_FUSE_REPAIR - wrong size (%"PRIu32":gids=%"PRIu32")",length,gids);
3360 			eptr->mode = KILL;
3361 			return;
3362 		}
3363 		gid = matoclserv_gid_storage(gids);
3364 		for (i=0 ; i<gids ; i++) {
3365 			gid[i] = get32bit(&data);
3366 		}
3367 	}
3368 	sessions_ugid_remap(eptr->sesdata,&uid,gid);
3369 	status = fs_repair(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,uid,gids,gid,&chunksnotchanged,&chunkserased,&chunksrepaired);
3370 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_REPAIR,(status!=MFS_STATUS_OK)?5:16);
3371 	put32bit(&ptr,msgid);
3372 	if (status!=0) {
3373 		put8bit(&ptr,status);
3374 	} else {
3375 		put32bit(&ptr,chunksnotchanged);
3376 		put32bit(&ptr,chunkserased);
3377 		put32bit(&ptr,chunksrepaired);
3378 	}
3379 }
3380 
matoclserv_fuse_check(matoclserventry * eptr,const uint8_t * data,uint32_t length)3381 void matoclserv_fuse_check(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
3382 	uint32_t inode;
3383 	uint32_t indx;
3384 	uint64_t chunkid;
3385 	uint32_t version;
3386 	uint8_t cs_data[100*7];
3387 	uint8_t count;
3388 	uint32_t i,chunkcount[12];
3389 	uint32_t msgid;
3390 	uint8_t *ptr;
3391 	uint8_t status;
3392 	if (length!=8 && length!=12) {
3393 		syslog(LOG_NOTICE,"CLTOMA_FUSE_CHECK - wrong size (%"PRIu32"/8|12)",length);
3394 		eptr->mode = KILL;
3395 		return;
3396 	}
3397 	msgid = get32bit(&data);
3398 	inode = get32bit(&data);
3399 	if (length==12) {
3400 		indx = get32bit(&data);
3401 		status = fs_filechunk(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,indx,&chunkid);
3402 		if (status!=MFS_STATUS_OK) {
3403 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_CHECK,5);
3404 			put32bit(&ptr,msgid);
3405 			put8bit(&ptr,status);
3406 			return;
3407 		}
3408 		if (chunkid>0) {
3409 			status = chunk_get_version_and_copies(chunkid,&version,&count,cs_data);
3410 			if (status!=MFS_STATUS_OK) {
3411 				ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_CHECK,5);
3412 				put32bit(&ptr,msgid);
3413 				put8bit(&ptr,status);
3414 				return;
3415 			}
3416 		} else {
3417 			version = 0;
3418 			count = 0;
3419 		}
3420 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_CHECK,16+count*7);
3421 		put32bit(&ptr,msgid);
3422 		put64bit(&ptr,chunkid);
3423 		put32bit(&ptr,version);
3424 		if (count>0) {
3425 			memcpy(ptr,cs_data,count*7);
3426 		}
3427 	} else {
3428 		status = fs_checkfile(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,chunkcount);
3429 		if (status!=MFS_STATUS_OK) {
3430 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_CHECK,5);
3431 			put32bit(&ptr,msgid);
3432 			put8bit(&ptr,status);
3433 			return;
3434 		}
3435 		if (eptr->version>=VERSION2INT(3,0,30)) {
3436 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_CHECK,52);
3437 			put32bit(&ptr,msgid);
3438 			for (i=0 ; i<12 ; i++) {
3439 				put32bit(&ptr,chunkcount[i]);
3440 			}
3441 		} else if (eptr->version>=VERSION2INT(1,6,23)) {
3442 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_CHECK,48);
3443 			put32bit(&ptr,msgid);
3444 			for (i=0 ; i<11 ; i++) {
3445 				put32bit(&ptr,chunkcount[i]);
3446 			}
3447 		} else {
3448 			uint8_t j;
3449 			j=0;
3450 			for (i=0 ; i<11 ; i++) {
3451 				if (chunkcount[i]>0) {
3452 					j++;
3453 				}
3454 			}
3455 			ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_CHECK,4+3*j);
3456 			put32bit(&ptr,msgid);
3457 			for (i=0 ; i<11 ; i++) {
3458 				if (chunkcount[i]>0) {
3459 					put8bit(&ptr,i);
3460 					if (chunkcount[i]<=65535) {
3461 						put16bit(&ptr,chunkcount[i]);
3462 					} else {
3463 						put16bit(&ptr,65535);
3464 					}
3465 				}
3466 			}
3467 		}
3468 	}
3469 }
3470 
3471 
matoclserv_fuse_gettrashtime(matoclserventry * eptr,const uint8_t * data,uint32_t length)3472 void matoclserv_fuse_gettrashtime(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
3473 	uint32_t inode;
3474 	uint8_t gmode;
3475 	void *fptr,*dptr;
3476 	uint32_t fnodes,dnodes;
3477 	uint32_t msgid;
3478 	uint8_t *ptr;
3479 	uint8_t status;
3480 	if (length!=9) {
3481 		syslog(LOG_NOTICE,"CLTOMA_FUSE_GETTRASHTIME - wrong size (%"PRIu32"/9)",length);
3482 		eptr->mode = KILL;
3483 		return;
3484 	}
3485 	msgid = get32bit(&data);
3486 	inode = get32bit(&data);
3487 	gmode = get8bit(&data);
3488 	status = fs_gettrashtime_prepare(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,gmode,&fptr,&dptr,&fnodes,&dnodes);
3489 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_GETTRASHTIME,(status!=MFS_STATUS_OK)?5:12+8*(fnodes+dnodes));
3490 	put32bit(&ptr,msgid);
3491 	if (status!=MFS_STATUS_OK) {
3492 		put8bit(&ptr,status);
3493 	} else {
3494 		put32bit(&ptr,fnodes);
3495 		put32bit(&ptr,dnodes);
3496 		fs_gettrashtime_store(fptr,dptr,ptr);
3497 	}
3498 }
3499 
matoclserv_fuse_settrashtime(matoclserventry * eptr,const uint8_t * data,uint32_t length)3500 void matoclserv_fuse_settrashtime(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
3501 	uint32_t inode,uid,trashtime;
3502 	uint32_t msgid;
3503 	uint8_t smode;
3504 	uint32_t changed,notchanged,notpermitted;
3505 	uint8_t *ptr;
3506 	uint8_t status;
3507 	if (length!=17) {
3508 		syslog(LOG_NOTICE,"CLTOMA_FUSE_SETTRASHTIME - wrong size (%"PRIu32"/17)",length);
3509 		eptr->mode = KILL;
3510 		return;
3511 	}
3512 	msgid = get32bit(&data);
3513 	inode = get32bit(&data);
3514 	uid = get32bit(&data);
3515 	sessions_ugid_remap(eptr->sesdata,&uid,NULL);
3516 	trashtime = get32bit(&data);
3517 	smode = get8bit(&data);
3518 	if (sessions_get_disables(eptr->sesdata)&DISABLE_SETTRASH) {
3519 		status = MFS_ERROR_EPERM;
3520 	} else {
3521 		status = sessions_check_trashtime(eptr->sesdata,smode&SMODE_TMASK,trashtime);
3522 	}
3523 	if (status==MFS_STATUS_OK) {
3524 		status = fs_settrashtime(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,uid,trashtime,smode,&changed,&notchanged,&notpermitted);
3525 	}
3526 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_SETTRASHTIME,(status!=MFS_STATUS_OK)?5:16);
3527 	put32bit(&ptr,msgid);
3528 	if (status!=MFS_STATUS_OK) {
3529 		put8bit(&ptr,status);
3530 	} else {
3531 		put32bit(&ptr,changed);
3532 		put32bit(&ptr,notchanged);
3533 		put32bit(&ptr,notpermitted);
3534 	}
3535 }
3536 
matoclserv_fuse_getsclass(matoclserventry * eptr,const uint8_t * data,uint32_t length)3537 void matoclserv_fuse_getsclass(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
3538 	uint32_t inode;
3539 	uint32_t msgid;
3540 	uint32_t fgtab[MAXSCLASS],dgtab[MAXSCLASS];
3541 	uint8_t nleng;
3542 	uint16_t i;
3543 	uint8_t fn,dn,gmode;
3544 	uint32_t psize;
3545 	uint8_t *ptr;
3546 	uint8_t status;
3547 	if (length!=9) {
3548 		syslog(LOG_NOTICE,"CLTOMA_FUSE_GETSCLASS - wrong size (%"PRIu32"/9)",length);
3549 		eptr->mode = KILL;
3550 		return;
3551 	}
3552 	msgid = get32bit(&data);
3553 	inode = get32bit(&data);
3554 	gmode = get8bit(&data);
3555 	status = fs_getsclass(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,gmode,fgtab,dgtab);
3556 	fn = 0;
3557 	dn = 0;
3558 	psize = 6;
3559 	if (status==MFS_STATUS_OK) {
3560 		for (i=1 ; i<MAXSCLASS ; i++) {
3561 			if (sclass_is_simple_goal(i)) {
3562 				if (fgtab[i]) {
3563 					fn++;
3564 					psize += 5;
3565 				}
3566 				if (dgtab[i]) {
3567 					dn++;
3568 					psize += 5;
3569 				}
3570 			} else if (eptr->version>=VERSION2INT(3,0,75)) {
3571 				if (fgtab[i]) {
3572 					fn++;
3573 					psize += 6 + sclass_get_nleng(i);
3574 				}
3575 				if (dgtab[i]) {
3576 					dn++;
3577 					psize += 6 + sclass_get_nleng(i);
3578 				}
3579 			}
3580 		}
3581 	}
3582 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_GETSCLASS,(status!=MFS_STATUS_OK)?5:psize);
3583 	put32bit(&ptr,msgid);
3584 	if (status!=MFS_STATUS_OK) {
3585 		put8bit(&ptr,status);
3586 	} else {
3587 		put8bit(&ptr,fn);
3588 		put8bit(&ptr,dn);
3589 		for (i=1 ; i<MAXSCLASS ; i++) {
3590 			if (fgtab[i]) {
3591 				if (sclass_is_simple_goal(i)) {
3592 					put8bit(&ptr,i);
3593 					put32bit(&ptr,fgtab[i]);
3594 				} else if (eptr->version>=VERSION2INT(3,0,75)) {
3595 					put8bit(&ptr,0xFF);
3596 					nleng = sclass_get_nleng(i);
3597 					put8bit(&ptr,nleng);
3598 					memcpy(ptr,sclass_get_name(i),nleng);
3599 					ptr+=nleng;
3600 					put32bit(&ptr,fgtab[i]);
3601 				}
3602 			}
3603 		}
3604 		for (i=1 ; i<MAXSCLASS ; i++) {
3605 			if (dgtab[i]) {
3606 				if (sclass_is_simple_goal(i)) {
3607 					put8bit(&ptr,i);
3608 					put32bit(&ptr,dgtab[i]);
3609 				} else if (eptr->version>=VERSION2INT(3,0,9)) {
3610 					put8bit(&ptr,0xFF);
3611 					nleng = sclass_get_nleng(i);
3612 					put8bit(&ptr,nleng);
3613 					memcpy(ptr,sclass_get_name(i),nleng);
3614 					ptr+=nleng;
3615 					put32bit(&ptr,dgtab[i]);
3616 				}
3617 			}
3618 		}
3619 	}
3620 }
3621 
matoclserv_fuse_setsclass(matoclserventry * eptr,const uint8_t * data,uint32_t length)3622 void matoclserv_fuse_setsclass(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
3623 	uint32_t inode,uid;
3624 	uint32_t msgid;
3625 	uint8_t setid,smode;
3626 	uint32_t changed,notchanged,notpermitted;
3627 	uint8_t scnleng;
3628 	uint8_t src_sclassid,dst_sclassid;
3629 	uint32_t pskip;
3630 	uint8_t *ptr;
3631 	uint8_t status;
3632 	if (length<14) {
3633 		syslog(LOG_NOTICE,"CLTOMA_FUSE_SETSCLASS - wrong size (%"PRIu32"/<14)",length);
3634 		eptr->mode = KILL;
3635 		return;
3636 	}
3637 	msgid = get32bit(&data);
3638 	inode = get32bit(&data);
3639 	uid = get32bit(&data);
3640 	sessions_ugid_remap(eptr->sesdata,&uid,NULL);
3641 	setid = get8bit(&data);
3642 	smode = get8bit(&data);
3643 	if (setid==0xFF) {
3644 		if ((smode&SMODE_TMASK)==SMODE_EXCHANGE) {
3645 			if (length<15) {
3646 				syslog(LOG_NOTICE,"CLTOMA_FUSE_SETSCLASS - wrong size (%"PRIu32"/<15)",length);
3647 				eptr->mode = KILL;
3648 				return;
3649 			}
3650 			scnleng = get8bit(&data);
3651 			src_sclassid = sclass_find_by_name(scnleng,data);
3652 			data += scnleng;
3653 			pskip = 15+scnleng;
3654 		} else {
3655 			pskip = 14;
3656 			src_sclassid = 0x1; // any non 0 value
3657 		}
3658 		if (length<pskip+1) {
3659 			syslog(LOG_NOTICE,"CLTOMA_FUSE_SETSCLASS - wrong size (%"PRIu32")",length);
3660 			eptr->mode = KILL;
3661 			return;
3662 		}
3663 		scnleng = get8bit(&data);
3664 		dst_sclassid = sclass_find_by_name(scnleng,data);
3665 		data += scnleng;
3666 		if (length<pskip+1+scnleng) {
3667 			syslog(LOG_NOTICE,"CLTOMA_FUSE_SETSCLASS - wrong size (%"PRIu32")",length);
3668 			eptr->mode = KILL;
3669 			return;
3670 		}
3671 		if (sessions_get_disables(eptr->sesdata)&DISABLE_SETSCLASS) {
3672 			status = MFS_ERROR_EPERM;
3673 		} else if (src_sclassid==0 || dst_sclassid==0) {
3674 			status = MFS_ERROR_EINVAL; // new status ? NOSUCHSCLASS ?
3675 		} else {
3676 			if (sclass_is_simple_goal(dst_sclassid)) {
3677 				status = sessions_check_goal(eptr->sesdata,smode&SMODE_TMASK,dst_sclassid);
3678 			} else {
3679 				status = MFS_STATUS_OK;
3680 			}
3681 		}
3682 	} else { // setid == goal
3683 		if (sessions_get_disables(eptr->sesdata)&DISABLE_SETSCLASS) {
3684 			status = MFS_ERROR_EPERM;
3685 		} else if (setid<1 || setid>9) {
3686 			status = MFS_ERROR_EINVAL;
3687 		} else {
3688 			src_sclassid = setid;
3689 			dst_sclassid = setid;
3690 			if (length!=14) {
3691 				syslog(LOG_NOTICE,"CLTOMA_FUSE_SETSCLASS (classic version) - wrong size (%"PRIu32"/14)",length);
3692 				eptr->mode = KILL;
3693 				return;
3694 			}
3695 			status = sessions_check_goal(eptr->sesdata,smode&SMODE_TMASK,setid);
3696 		}
3697 	}
3698 	if (status==MFS_STATUS_OK) {
3699 		status = fs_setsclass(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,uid,src_sclassid,dst_sclassid,smode,&changed,&notchanged,&notpermitted);
3700 	}
3701 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_SETSCLASS,(status!=MFS_STATUS_OK)?5:16);
3702 	put32bit(&ptr,msgid);
3703 	if (status!=MFS_STATUS_OK) {
3704 		put8bit(&ptr,status);
3705 	} else {
3706 		put32bit(&ptr,changed);
3707 		put32bit(&ptr,notchanged);
3708 		put32bit(&ptr,notpermitted);
3709 	}
3710 }
3711 
matoclserv_fuse_geteattr(matoclserventry * eptr,const uint8_t * data,uint32_t length)3712 void matoclserv_fuse_geteattr(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
3713 	uint32_t inode;
3714 	uint32_t msgid;
3715 	uint32_t feattrtab[1<<EATTR_BITS],deattrtab[1<<EATTR_BITS];
3716 	uint8_t gmode;
3717 	uint16_t i,fn,dn;
3718 	uint8_t *ptr;
3719 	uint8_t status;
3720 	if (length!=9) {
3721 		syslog(LOG_NOTICE,"CLTOMA_FUSE_GETEATTR - wrong size (%"PRIu32"/9)",length);
3722 		eptr->mode = KILL;
3723 		return;
3724 	}
3725 	msgid = get32bit(&data);
3726 	inode = get32bit(&data);
3727 	gmode = get8bit(&data);
3728 	status = fs_geteattr(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,gmode,feattrtab,deattrtab);
3729 	if (eptr->version < VERSION2INT(3,0,30)) {
3730 		for (i=16 ; i<(1<<EATTR_BITS) ; i++) {
3731 			feattrtab[i&0xF] += feattrtab[i];
3732 			feattrtab[i] = 0;
3733 			deattrtab[i&0xF] += deattrtab[i];
3734 			deattrtab[i] = 0;
3735 		}
3736 	} else if (eptr->version < VERSION2INT(3,0,113)) {
3737 		for (i=32 ; i<(1<<EATTR_BITS) ; i++) {
3738 			feattrtab[i&0x1F] += feattrtab[i];
3739 			feattrtab[i] = 0;
3740 			deattrtab[i&0x1F] += deattrtab[i];
3741 			deattrtab[i] = 0;
3742 		}
3743 	}
3744 	fn=0;
3745 	dn=0;
3746 	if (status==MFS_STATUS_OK) {
3747 		for (i=0 ; i<(1<<EATTR_BITS) ; i++) {
3748 			if (feattrtab[i] && fn<255) {
3749 				fn++;
3750 			} else {
3751 				feattrtab[i]=0; // TODO increase fn and dn in packets
3752 			}
3753 			if (deattrtab[i] && dn<255) {
3754 				dn++;
3755 			} else {
3756 				deattrtab[i]=0;
3757 			}
3758 		}
3759 	}
3760 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_GETEATTR,(status!=MFS_STATUS_OK)?5:6+5*(fn+dn));
3761 	put32bit(&ptr,msgid);
3762 	if (status!=MFS_STATUS_OK) {
3763 		put8bit(&ptr,status);
3764 	} else {
3765 		put8bit(&ptr,fn);
3766 		put8bit(&ptr,dn);
3767 		for (i=0 ; i<(1<<EATTR_BITS) ; i++) {
3768 			if (feattrtab[i]) {
3769 				put8bit(&ptr,i);
3770 				put32bit(&ptr,feattrtab[i]);
3771 			}
3772 		}
3773 		for (i=0 ; i<(1<<EATTR_BITS) ; i++) {
3774 			if (deattrtab[i]) {
3775 				put8bit(&ptr,i);
3776 				put32bit(&ptr,deattrtab[i]);
3777 			}
3778 		}
3779 	}
3780 }
3781 
matoclserv_fuse_seteattr(matoclserventry * eptr,const uint8_t * data,uint32_t length)3782 void matoclserv_fuse_seteattr(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
3783 	uint32_t inode,uid;
3784 	uint32_t msgid;
3785 	uint8_t eattr,smode;
3786 	uint32_t changed,notchanged,notpermitted;
3787 	uint8_t *ptr;
3788 	uint8_t status;
3789 	if (length!=14) {
3790 		syslog(LOG_NOTICE,"CLTOMA_FUSE_SETEATTR - wrong size (%"PRIu32"/14)",length);
3791 		eptr->mode = KILL;
3792 		return;
3793 	}
3794 	msgid = get32bit(&data);
3795 	inode = get32bit(&data);
3796 	uid = get32bit(&data);
3797 	sessions_ugid_remap(eptr->sesdata,&uid,NULL);
3798 	eattr = get8bit(&data);
3799 	smode = get8bit(&data);
3800 	if (sessions_get_disables(eptr->sesdata)&DISABLE_SETEATTR) {
3801 		status = MFS_ERROR_EPERM;
3802 	} else {
3803 		status = fs_seteattr(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,uid,eattr,smode,&changed,&notchanged,&notpermitted);
3804 	}
3805 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_SETEATTR,(status!=MFS_STATUS_OK)?5:16);
3806 	put32bit(&ptr,msgid);
3807 	if (status!=MFS_STATUS_OK) {
3808 		put8bit(&ptr,status);
3809 	} else {
3810 		put32bit(&ptr,changed);
3811 		put32bit(&ptr,notchanged);
3812 		put32bit(&ptr,notpermitted);
3813 	}
3814 }
3815 
matoclserv_fuse_parents(matoclserventry * eptr,const uint8_t * data,uint32_t length)3816 void matoclserv_fuse_parents(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
3817 	uint32_t inode;
3818 	uint32_t msgid;
3819 	uint32_t pcount;
3820 	uint8_t *ptr;
3821 	uint8_t status;
3822 	if (length!=8) {
3823 		syslog(LOG_NOTICE,"CLTOMA_FUSE_PARENTS - wrong size (%"PRIu32"/8)",length);
3824 		eptr->mode = KILL;
3825 		return;
3826 	}
3827 	msgid = get32bit(&data);
3828 	inode = get32bit(&data);
3829 	status = fs_get_parents_count(sessions_get_rootinode(eptr->sesdata),inode,&pcount);
3830 	if (status!=MFS_STATUS_OK) {
3831 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_PARENTS,5);
3832 		put32bit(&ptr,msgid);
3833 		put8bit(&ptr,status);
3834 	} else {
3835 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_PARENTS,4+4*pcount);
3836 		put32bit(&ptr,msgid);
3837 		fs_get_parents_data(sessions_get_rootinode(eptr->sesdata),inode,ptr);
3838 	}
3839 }
3840 
matoclserv_fuse_paths(matoclserventry * eptr,const uint8_t * data,uint32_t length)3841 void matoclserv_fuse_paths(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
3842 	uint32_t inode;
3843 	uint32_t msgid;
3844 	uint32_t psize;
3845 	uint8_t *ptr;
3846 	uint8_t status;
3847 	if (length!=8) {
3848 		syslog(LOG_NOTICE,"CLTOMA_FUSE_PATHS - wrong size (%"PRIu32"/8)",length);
3849 		eptr->mode = KILL;
3850 		return;
3851 	}
3852 	msgid = get32bit(&data);
3853 	inode = get32bit(&data);
3854 	status = fs_get_paths_size(sessions_get_rootinode(eptr->sesdata),inode,&psize);
3855 	if (status!=MFS_STATUS_OK) {
3856 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_PATHS,5);
3857 		put32bit(&ptr,msgid);
3858 		put8bit(&ptr,status);
3859 	} else {
3860 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_PATHS,4+psize);
3861 		put32bit(&ptr,msgid);
3862 		fs_get_paths_data(sessions_get_rootinode(eptr->sesdata),inode,ptr);
3863 	}
3864 }
3865 
matoclserv_fuse_getxattr(matoclserventry * eptr,const uint8_t * data,uint32_t length)3866 void matoclserv_fuse_getxattr(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
3867 	uint32_t inode,uid,gids;
3868 	uint32_t *gid;
3869 	uint32_t i;
3870 	uint32_t msgid;
3871 	uint8_t opened;
3872 	uint8_t mode;
3873 	uint8_t *ptr;
3874 	uint8_t status;
3875 	uint8_t anleng;
3876 	const uint8_t *attrname;
3877 	if (length<19) {
3878 		syslog(LOG_NOTICE,"CLTOMA_FUSE_GETXATTR - wrong size (%"PRIu32")",length);
3879 		eptr->mode = KILL;
3880 		return;
3881 	}
3882 	opened = 0; // makes gcc happy
3883 	gid = NULL; // makes gcc happy
3884 	msgid = get32bit(&data);
3885 	inode = get32bit(&data);
3886 	if (eptr->version<VERSION2INT(2,0,0)) {
3887 		opened = get8bit(&data);
3888 		uid = get32bit(&data);
3889 		gids = 1;
3890 		gid = matoclserv_gid_storage(gids);
3891 		gid[0] = get32bit(&data);
3892 	}
3893 	anleng = get8bit(&data);
3894 	attrname = data;
3895 	data+=anleng;
3896 	if (length<19U+anleng) {
3897 		syslog(LOG_NOTICE,"CLTOMA_FUSE_GETXATTR - wrong size (%"PRIu32":anleng=%"PRIu8")",length,anleng);
3898 		eptr->mode = KILL;
3899 		return;
3900 	}
3901 	mode = get8bit(&data);
3902 	if (eptr->version>=VERSION2INT(2,0,0)) {
3903 		opened = get8bit(&data);
3904 		uid = get32bit(&data);
3905 		if (length==19U+anleng) {
3906 			gids = 1;
3907 			gid = matoclserv_gid_storage(gids);
3908 			gid[0] = get32bit(&data);
3909 		} else {
3910 			gids = get32bit(&data);
3911 			if (length!=19U+anleng+4*gids) {
3912 				syslog(LOG_NOTICE,"CLTOMA_FUSE_GETXATTR - wrong size (%"PRIu32":anleng=%"PRIu8":gids=%"PRIu32")",length,anleng,gids);
3913 				eptr->mode = KILL;
3914 				return;
3915 			}
3916 			gid = matoclserv_gid_storage(gids);
3917 			for (i=0 ; i<gids ; i++) {
3918 				gid[i] = get32bit(&data);
3919 			}
3920 		}
3921 	}
3922 	sessions_ugid_remap(eptr->sesdata,&uid,gid);
3923 	if (mode!=MFS_XATTR_GETA_DATA && mode!=MFS_XATTR_LENGTH_ONLY) {
3924 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_GETXATTR,5);
3925 		put32bit(&ptr,msgid);
3926 		put8bit(&ptr,MFS_ERROR_EINVAL);
3927 	} else if (anleng==0) {
3928 		void *xanode;
3929 		uint32_t xasize;
3930 		status = fs_listxattr_leng(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,opened,uid,gids,gid,&xanode,&xasize);
3931 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_GETXATTR,(status!=MFS_STATUS_OK)?5:8+((mode==MFS_XATTR_GETA_DATA)?xasize:0));
3932 		put32bit(&ptr,msgid);
3933 		if (status!=MFS_STATUS_OK) {
3934 			put8bit(&ptr,status);
3935 		} else {
3936 			put32bit(&ptr,xasize);
3937 			if (mode==MFS_XATTR_GETA_DATA && xasize>0) {
3938 				fs_listxattr_data(xanode,ptr);
3939 			}
3940 		}
3941 	} else {
3942 		const uint8_t *attrvalue;
3943 		uint32_t avleng;
3944 		status = fs_getxattr(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,opened,uid,gids,gid,anleng,attrname,&avleng,&attrvalue);
3945 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_GETXATTR,(status!=MFS_STATUS_OK)?5:8+((mode==MFS_XATTR_GETA_DATA)?avleng:0));
3946 		put32bit(&ptr,msgid);
3947 		if (status!=MFS_STATUS_OK) {
3948 			put8bit(&ptr,status);
3949 		} else {
3950 			put32bit(&ptr,avleng);
3951 			if (mode==MFS_XATTR_GETA_DATA && avleng>0) {
3952 				memcpy(ptr,attrvalue,avleng);
3953 			}
3954 		}
3955 	}
3956 }
3957 
matoclserv_fuse_setxattr(matoclserventry * eptr,const uint8_t * data,uint32_t length)3958 void matoclserv_fuse_setxattr(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
3959 	uint32_t inode,uid,gids;
3960 	uint32_t *gid;
3961 	uint32_t i;
3962 	uint32_t msgid;
3963 	const uint8_t *attrname,*attrvalue;
3964 	uint8_t opened;
3965 	uint8_t anleng;
3966 	uint32_t avleng;
3967 	uint8_t mode;
3968 	uint8_t *ptr;
3969 	uint8_t status;
3970 	if (length<23) {
3971 		syslog(LOG_NOTICE,"CLTOMA_FUSE_SETXATTR - wrong size (%"PRIu32")",length);
3972 		eptr->mode = KILL;
3973 		return;
3974 	}
3975 	opened = 0; // makes gcc happy
3976 	gid = NULL; // makes gcc happy
3977 	msgid = get32bit(&data);
3978 	inode = get32bit(&data);
3979 	if (eptr->version<VERSION2INT(2,0,0)) {
3980 		opened = get8bit(&data);
3981 		uid = get32bit(&data);
3982 		gids = 1;
3983 		gid = matoclserv_gid_storage(gids);
3984 		gid[0] = get32bit(&data);
3985 	}
3986 	anleng = get8bit(&data);
3987 	if (length<23U+anleng) {
3988 		syslog(LOG_NOTICE,"CLTOMA_FUSE_SETXATTR - wrong size (%"PRIu32":anleng=%"PRIu8")",length,anleng);
3989 		eptr->mode = KILL;
3990 		return;
3991 	}
3992 	attrname = data;
3993 	data += anleng;
3994 	avleng = get32bit(&data);
3995 	if (length<23U+anleng+avleng) {
3996 		syslog(LOG_NOTICE,"CLTOMA_FUSE_SETXATTR - wrong size (%"PRIu32":anleng=%"PRIu8":avleng=%"PRIu32")",length,anleng,avleng);
3997 		eptr->mode = KILL;
3998 		return;
3999 	}
4000 	attrvalue = data;
4001 	data += avleng;
4002 	mode = get8bit(&data);
4003 	if (eptr->version>=VERSION2INT(2,0,0)) {
4004 		opened = get8bit(&data);
4005 		uid = get32bit(&data);
4006 		if (length==23U+anleng+avleng) {
4007 			gids = 1;
4008 			gid = matoclserv_gid_storage(gids);
4009 			gid[0] = get32bit(&data);
4010 		} else {
4011 			gids = get32bit(&data);
4012 			if (length!=23U+anleng+avleng+4*gids) {
4013 				syslog(LOG_NOTICE,"CLTOMA_FUSE_SETXATTR - wrong size (%"PRIu32":anleng=%"PRIu8":avleng=%"PRIu32":gids=%"PRIu32")",length,anleng,avleng,gids);
4014 				eptr->mode = KILL;
4015 				return;
4016 			}
4017 			gid = matoclserv_gid_storage(gids);
4018 			for (i=0 ; i<gids ; i++) {
4019 				gid[i] = get32bit(&data);
4020 			}
4021 		}
4022 	}
4023 	sessions_ugid_remap(eptr->sesdata,&uid,gid);
4024 	if (sessions_get_disables(eptr->sesdata)&DISABLE_SETXATTR) {
4025 		status = MFS_ERROR_EPERM;
4026 	} else {
4027 		status = fs_setxattr(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,opened,uid,gids,gid,anleng,attrname,avleng,attrvalue,mode);
4028 	}
4029 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_SETXATTR,5);
4030 	put32bit(&ptr,msgid);
4031 	put8bit(&ptr,status);
4032 }
4033 
matoclserv_fuse_getfacl(matoclserventry * eptr,const uint8_t * data,uint32_t length)4034 void matoclserv_fuse_getfacl(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
4035 	uint32_t inode;
4036 //	uint32_t uid,gids;
4037 //	uint32_t *gid;
4038 //	uint32_t i;
4039 //	uint8_t opened;
4040 	uint32_t msgid;
4041 	uint8_t acltype;
4042 	uint8_t *ptr;
4043 	uint8_t status;
4044 	void *c;
4045 	uint16_t userperm;
4046 	uint16_t groupperm;
4047 	uint16_t otherperm;
4048 	uint16_t mask;
4049 	uint16_t namedusers;
4050 	uint16_t namedgroups;
4051 	uint32_t aclleng;
4052 	if (length<9) {
4053 		syslog(LOG_NOTICE,"CLTOMA_FUSE_GETFACL - wrong size (%"PRIu32")",length);
4054 		eptr->mode = KILL;
4055 		return;
4056 	}
4057 	msgid = get32bit(&data);
4058 	inode = get32bit(&data);
4059 	acltype = get8bit(&data);
4060 	if (length>9) { // just sanity length check
4061 		if (length<18) {
4062 			syslog(LOG_NOTICE,"CLTOMA_FUSE_GETFACL - wrong size (%"PRIu32")",length);
4063 			eptr->mode = KILL;
4064 			return;
4065 		} else if (length>18) {
4066 			uint32_t gids;
4067 			data+=5;
4068 			gids = get32bit(&data);
4069 			if (length!=18+4*gids) {
4070 				syslog(LOG_NOTICE,"CLTOMA_FUSE_GETFACL - wrong size (%"PRIu32":gids=%"PRIu32")",length,gids);
4071 				eptr->mode = KILL;
4072 				return;
4073 			}
4074 		}
4075 	}
4076 #if 0
4077 	// for future use (rich acl)
4078 	opened = get8bit(&data);
4079 	uid = get32bit(&data);
4080 	if (length==18) {
4081 		gids = 1;
4082 		gid = matoclserv_gid_storage(gids);
4083 		gid[0] = get32bit(&data);
4084 	} else {
4085 		gids = get32bit(&data);
4086 		if (length!=18+4*gids) {
4087 			syslog(LOG_NOTICE,"CLTOMA_FUSE_GETFACL - wrong size (%"PRIu32":gids=%"PRIu32")",length,gids);
4088 			eptr->mode = KILL;
4089 			return;
4090 		}
4091 		gid = matoclserv_gid_storage(gids);
4092 		for (i=0 ; i<gids ; i++) {
4093 			gid[i] = get32bit(&data);
4094 		}
4095 	}
4096 	sessions_ugid_remap(eptr->sesdata,&uid,gid);
4097 #endif
4098 	status = fs_getfacl_size(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,/*opened,uid,gids,gid,*/acltype,&c,&aclleng);
4099 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_GETFACL,(status!=MFS_STATUS_OK)?5:16+aclleng);
4100 	if (status!=MFS_STATUS_OK) {
4101 		put32bit(&ptr,msgid);
4102 		put8bit(&ptr,status);
4103 	} else {
4104 		fs_getfacl_data(c,&userperm,&groupperm,&otherperm,&mask,&namedusers,&namedgroups,ptr+16);
4105 		put32bit(&ptr,msgid);
4106 		put16bit(&ptr,userperm);
4107 		put16bit(&ptr,groupperm);
4108 		put16bit(&ptr,otherperm);
4109 		put16bit(&ptr,mask);
4110 		put16bit(&ptr,namedusers);
4111 		put16bit(&ptr,namedgroups);
4112 	}
4113 }
4114 
matoclserv_fuse_setfacl(matoclserventry * eptr,const uint8_t * data,uint32_t length)4115 void matoclserv_fuse_setfacl(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
4116 	uint32_t inode;
4117 	uint32_t uid;
4118 	uint32_t msgid;
4119 	uint8_t acltype;
4120 	uint16_t userperm;
4121 	uint16_t groupperm;
4122 	uint16_t otherperm;
4123 	uint16_t mask;
4124 	uint16_t namedusers;
4125 	uint16_t namedgroups;
4126 	uint8_t *ptr;
4127 	uint8_t status;
4128 	if (length<25) {
4129 		syslog(LOG_NOTICE,"CLTOMA_FUSE_SETFACL - wrong size (%"PRIu32")",length);
4130 		eptr->mode = KILL;
4131 		return;
4132 	}
4133 	msgid = get32bit(&data);
4134 	inode = get32bit(&data);
4135 	uid = get32bit(&data);
4136 	sessions_ugid_remap(eptr->sesdata,&uid,NULL);
4137 	acltype = get8bit(&data);
4138 	userperm = get16bit(&data);
4139 	groupperm = get16bit(&data);
4140 	otherperm = get16bit(&data);
4141 	mask = get16bit(&data);
4142 	namedusers = get16bit(&data);
4143 	namedgroups = get16bit(&data);
4144 	if (length!=(namedusers+namedgroups)*6U+25U) {
4145 		syslog(LOG_NOTICE,"CLTOMA_FUSE_SETFACL - wrong size (%"PRIu32":namedusers=%"PRIu16":namedgroups=%"PRIu16")",length,namedusers,namedgroups);
4146 		eptr->mode = KILL;
4147 		return;
4148 	}
4149 //	uid = get32bit(&data);
4150 //	gid = get32bit(&data);
4151 //	sessions_ugid_remap(eptr->sesdata,&uid,&gid);
4152 	if (sessions_get_disables(eptr->sesdata)&DISABLE_SETFACL) {
4153 		status = MFS_ERROR_EPERM;
4154 	} else {
4155 		status = fs_setfacl(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,uid,acltype,userperm,groupperm,otherperm,mask,namedusers,namedgroups,data);
4156 	}
4157 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_SETFACL,5);
4158 	put32bit(&ptr,msgid);
4159 	put8bit(&ptr,status);
4160 }
4161 
matoclserv_fuse_append_slice(matoclserventry * eptr,const uint8_t * data,uint32_t length)4162 void matoclserv_fuse_append_slice(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
4163 	uint32_t inode,inode_src,uid,gids;
4164 	uint32_t slice_from,slice_to;
4165 	uint32_t *gid;
4166 	uint32_t i;
4167 	uint32_t msgid;
4168 	uint64_t fleng;
4169 	uint8_t *ptr;
4170 	uint8_t status;
4171 	uint8_t flags;
4172 	if (length<20 || ((length&1)==1 && length<29)) {
4173 		syslog(LOG_NOTICE,"CLTOMA_FUSE_APPEND_SLICE - wrong size (%"PRIu32"/20+|29+)",length);
4174 		eptr->mode = KILL;
4175 		return;
4176 	}
4177 	msgid = get32bit(&data);
4178 	if (length&1) {
4179 		flags = get8bit(&data);
4180 	} else {
4181 		flags = 0;
4182 	}
4183 	inode = get32bit(&data);
4184 	inode_src = get32bit(&data);
4185 	if (length&1) {
4186 		slice_from = get32bit(&data);
4187 		slice_to = get32bit(&data);
4188 	} else {
4189 		slice_from = 0;
4190 		slice_to = 0;
4191 	}
4192 	uid = get32bit(&data);
4193 	if (length==20) {
4194 		gids = 1;
4195 		gid = matoclserv_gid_storage(gids);
4196 		gid[0] = get32bit(&data);
4197 	} else {
4198 		gids = get32bit(&data);
4199 		if (length!=20+4*gids && length!=29+4*gids) {
4200 			syslog(LOG_NOTICE,"CLTOMA_FUSE_APPEND_SLICE - wrong size (%"PRIu32":gids=%"PRIu32")",length,gids);
4201 			eptr->mode = KILL;
4202 			return;
4203 		}
4204 		gid = matoclserv_gid_storage(gids);
4205 		for (i=0 ; i<gids ; i++) {
4206 			gid[i] = get32bit(&data);
4207 		}
4208 	}
4209 	sessions_ugid_remap(eptr->sesdata,&uid,gid);
4210 	if (sessions_get_disables(eptr->sesdata)&DISABLE_APPENDCHUNKS) {
4211 		status = MFS_ERROR_EPERM;
4212 	} else {
4213 		status = fs_append_slice(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),flags,inode,inode_src,slice_from,slice_to,uid,gids,gid,&fleng);
4214 	}
4215 	if (status==MFS_STATUS_OK) {
4216 		matoclserv_fuse_fleng_has_changed(NULL,inode,fleng);
4217 	}
4218 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_APPEND_SLICE,5);
4219 	put32bit(&ptr,msgid);
4220 	put8bit(&ptr,status);
4221 }
4222 
matoclserv_fuse_snapshot(matoclserventry * eptr,const uint8_t * data,uint32_t length)4223 void matoclserv_fuse_snapshot(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
4224 	uint32_t inode,inode_dst;
4225 	uint8_t nleng_dst;
4226 	const uint8_t *name_dst;
4227 	uint32_t uid,gids;
4228 	uint32_t *gid;
4229 	uint32_t i;
4230 	uint8_t smode;
4231 	uint16_t requmask;
4232 	uint32_t msgid;
4233 	uint8_t *ptr;
4234 	uint8_t status;
4235 	if (length<22) {
4236 		syslog(LOG_NOTICE,"CLTOMA_FUSE_SNAPSHOT - wrong size (%"PRIu32")",length);
4237 		eptr->mode = KILL;
4238 		return;
4239 	}
4240 	msgid = get32bit(&data);
4241 	inode = get32bit(&data);
4242 	inode_dst = get32bit(&data);
4243 	nleng_dst = get8bit(&data);
4244 	if (length!=22U+nleng_dst && length<24U+nleng_dst) {
4245 		syslog(LOG_NOTICE,"CLTOMA_FUSE_SNAPSHOT - wrong size (%"PRIu32":nleng_dst=%"PRIu8")",length,nleng_dst);
4246 		eptr->mode = KILL;
4247 		return;
4248 	}
4249 	name_dst = data;
4250 	data += nleng_dst;
4251 	uid = get32bit(&data);
4252 	if (length<=24U+nleng_dst) {
4253 		gids = 1;
4254 		gid = matoclserv_gid_storage(gids);
4255 		gid[0] = get32bit(&data);
4256 	} else {
4257 		gids = get32bit(&data);
4258 		if (length!=24U+nleng_dst+4*gids) {
4259 			syslog(LOG_NOTICE,"CLTOMA_FUSE_SNAPSHOT - wrong size (%"PRIu32":nleng_dst=%"PRIu8":gids=%"PRIu32")",length,nleng_dst,gids);
4260 			eptr->mode = KILL;
4261 			return;
4262 		}
4263 		gid = matoclserv_gid_storage(gids);
4264 		for (i=0 ; i<gids ; i++) {
4265 			gid[i] = get32bit(&data);
4266 		}
4267 	}
4268 	sessions_ugid_remap(eptr->sesdata,&uid,gid);
4269 	smode = get8bit(&data);
4270 	if (length>=24U+nleng_dst) {
4271 		requmask = get16bit(&data);
4272 	} else {
4273 		smode &= ~SNAPSHOT_MODE_CPLIKE_ATTR;
4274 		requmask = 0;
4275 	}
4276 	requmask |= sessions_get_umask(eptr->sesdata);
4277 	status = MFS_STATUS_OK;
4278 	if (smode & SNAPSHOT_MODE_DELETE) {
4279 		if (sessions_get_disables(eptr->sesdata)&(DISABLE_UNLINK|DISABLE_RMDIR)) {
4280 			status = MFS_ERROR_EPERM;
4281 		}
4282 	} else {
4283 		if (sessions_get_disables(eptr->sesdata)&DISABLE_SNAPSHOT) {
4284 			status = MFS_ERROR_EPERM;
4285 		}
4286 	}
4287 	if (status==MFS_STATUS_OK) {
4288 		status = fs_snapshot(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,inode_dst,nleng_dst,name_dst,uid,gids,gid,smode,requmask);
4289 	}
4290 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_SNAPSHOT,5);
4291 	put32bit(&ptr,msgid);
4292 	put8bit(&ptr,status);
4293 }
4294 
matoclserv_fuse_quotacontrol(matoclserventry * eptr,const uint8_t * data,uint32_t length)4295 void matoclserv_fuse_quotacontrol(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
4296 	uint8_t flags,del;
4297 	uint32_t sinodes,hinodes,curinodes;
4298 	uint64_t slength,ssize,srealsize,hlength,hsize,hrealsize,curlength,cursize,currealsize;
4299 	uint32_t msgid,inode,graceperiod;
4300 	uint8_t *ptr;
4301 	uint8_t status;
4302 	if (length!=65 && length!=69 && length!=9) {
4303 		syslog(LOG_NOTICE,"CLTOMA_FUSE_QUOTACONTROL - wrong size (%"PRIu32")",length);
4304 		eptr->mode = KILL;
4305 		return;
4306 	}
4307 	msgid = get32bit(&data);
4308 	inode = get32bit(&data);
4309 	flags = get8bit(&data);
4310 	if (length==65 || length==69) {
4311 		if (length==69) {
4312 			graceperiod = get32bit(&data);
4313 		} else {
4314 			graceperiod = 0;
4315 		}
4316 		sinodes = get32bit(&data);
4317 		slength = get64bit(&data);
4318 		ssize = get64bit(&data);
4319 		srealsize = get64bit(&data);
4320 		hinodes = get32bit(&data);
4321 		hlength = get64bit(&data);
4322 		hsize = get64bit(&data);
4323 		hrealsize = get64bit(&data);
4324 		del=0;
4325 	} else {
4326 		del=1;
4327 	}
4328 	if (flags && sessions_is_root_remapped(eptr->sesdata)) {
4329 		status = MFS_ERROR_EACCES;
4330 	} else {
4331 		status = fs_quotacontrol(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,del,&flags,&graceperiod,&sinodes,&slength,&ssize,&srealsize,&hinodes,&hlength,&hsize,&hrealsize,&curinodes,&curlength,&cursize,&currealsize);
4332 	}
4333 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_QUOTACONTROL,(status!=MFS_STATUS_OK)?5:(eptr->version>=VERSION2INT(3,0,9))?93:89);
4334 	put32bit(&ptr,msgid);
4335 	if (status!=MFS_STATUS_OK) {
4336 		put8bit(&ptr,status);
4337 	} else {
4338 		put8bit(&ptr,flags);
4339 		if (eptr->version>=VERSION2INT(3,0,9)) {
4340 			put32bit(&ptr,graceperiod);
4341 		}
4342 		put32bit(&ptr,sinodes);
4343 		put64bit(&ptr,slength);
4344 		put64bit(&ptr,ssize);
4345 		put64bit(&ptr,srealsize);
4346 		put32bit(&ptr,hinodes);
4347 		put64bit(&ptr,hlength);
4348 		put64bit(&ptr,hsize);
4349 		put64bit(&ptr,hrealsize);
4350 		put32bit(&ptr,curinodes);
4351 		put64bit(&ptr,curlength);
4352 		put64bit(&ptr,cursize);
4353 		put64bit(&ptr,currealsize);
4354 	}
4355 }
4356 
matoclserv_fuse_archctl(matoclserventry * eptr,const uint8_t * data,uint32_t length)4357 void matoclserv_fuse_archctl(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
4358 	uint32_t inode;
4359 	uint32_t msgid;
4360 	uint8_t cmd,status;
4361 	uint8_t *ptr;
4362 	if (length!=13 && length!=9) {
4363 		syslog(LOG_NOTICE,"CLTOMA_FUSE_ARCHCTL - wrong size (%"PRIu32"/9|13)",length);
4364 		eptr->mode = KILL;
4365 		return;
4366 	}
4367 	msgid = get32bit(&data);
4368 	inode = get32bit(&data);
4369 	cmd = get8bit(&data);
4370 	if (cmd==ARCHCTL_GET) {
4371 		uint32_t archinodes,partinodes,notarchinodes;
4372 		uint64_t archchunks,notarchchunks;
4373 		if (length!=9) {
4374 			syslog(LOG_NOTICE,"CLTOMA_FUSE_ARCHCTL (GET) - wrong size (%"PRIu32"/9)",length);
4375 			eptr->mode = KILL;
4376 			return;
4377 		}
4378 		status = fs_archget(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,&archchunks,&notarchchunks,&archinodes,&partinodes,&notarchinodes);
4379 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_ARCHCTL,(status!=MFS_STATUS_OK)?5:32);
4380 		put32bit(&ptr,msgid);
4381 		if (status!=MFS_STATUS_OK) {
4382 			put8bit(&ptr,status);
4383 		} else {
4384 			put64bit(&ptr,archchunks);
4385 			put64bit(&ptr,notarchchunks);
4386 			put32bit(&ptr,archinodes);
4387 			put32bit(&ptr,partinodes);
4388 			put32bit(&ptr,notarchinodes);
4389 		}
4390 	} else {
4391 		uint32_t uid;
4392 		uint64_t changed,notchanged;
4393 		uint32_t notpermitted;
4394 		if (length!=13) {
4395 			syslog(LOG_NOTICE,"CLTOMA_FUSE_ARCHCTL (SET/CLR) - wrong size (%"PRIu32"/13)",length);
4396 			eptr->mode = KILL;
4397 			return;
4398 		}
4399 		uid = get32bit(&data);
4400 		sessions_ugid_remap(eptr->sesdata,&uid,NULL);
4401 		if (sessions_get_disables(eptr->sesdata)&DISABLE_SETEATTR) {
4402 			status = MFS_ERROR_EPERM;
4403 		} else {
4404 			status = fs_archchg(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,uid,cmd,&changed,&notchanged,&notpermitted);
4405 		}
4406 		ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_ARCHCTL,(status!=MFS_STATUS_OK)?5:24);
4407 		put32bit(&ptr,msgid);
4408 		if (status!=MFS_STATUS_OK) {
4409 			put8bit(&ptr,status);
4410 		} else {
4411 			put64bit(&ptr,changed);
4412 			put64bit(&ptr,notchanged);
4413 			put32bit(&ptr,notpermitted);
4414 		}
4415 	}
4416 }
4417 
matoclserv_sclass_create(matoclserventry * eptr,const uint8_t * data,uint32_t length)4418 void matoclserv_sclass_create(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
4419 	uint32_t msgid;
4420 	uint8_t nleng;
4421 	uint8_t fver;
4422 	uint8_t i;
4423 	uint32_t create_labelmasks[9*MASKORGROUP];
4424 	uint32_t keep_labelmasks[9*MASKORGROUP];
4425 	uint32_t arch_labelmasks[9*MASKORGROUP];
4426 	uint8_t mode;
4427 	uint8_t create_labelscnt;
4428 	uint8_t keep_labelscnt;
4429 	uint8_t arch_labelscnt;
4430 	uint16_t arch_delay;
4431 	uint8_t admin_only;
4432 	const uint8_t *name;
4433 	uint8_t *ptr;
4434 	uint8_t status;
4435 
4436 	if (length<5U) {
4437 		syslog(LOG_NOTICE,"CLTOMA_SCLASS_CREATE - wrong size (%"PRIu32")",length);
4438 		eptr->mode = KILL;
4439 		return;
4440 	}
4441 	msgid = get32bit(&data);
4442 	if (sessions_get_sesflags(eptr->sesdata)&SESFLAG_ADMIN) {
4443 		nleng = get8bit(&data);
4444 		name = data;
4445 		data += nleng;
4446 		if (length<6U+nleng) {
4447 			syslog(LOG_NOTICE,"CLTOMA_SCLASS_CREATE - wrong size (%"PRIu32":nleng=%"PRIu8")",length,nleng);
4448 			eptr->mode = KILL;
4449 			return;
4450 		}
4451 		fver = get8bit(&data);
4452 		if (fver==0) {
4453 			if (length<13U+nleng) {
4454 				syslog(LOG_NOTICE,"CLTOMA_SCLASS_CREATE - wrong size (%"PRIu32":nleng=%"PRIu8")",length,nleng);
4455 				eptr->mode = KILL;
4456 				return;
4457 			}
4458 			admin_only = get8bit(&data);
4459 			mode = get8bit(&data);
4460 			arch_delay = get16bit(&data);
4461 			create_labelscnt = get8bit(&data);
4462 			keep_labelscnt = get8bit(&data);
4463 			arch_labelscnt = get8bit(&data);
4464 			if (length!=13U+nleng+(create_labelscnt+keep_labelscnt+arch_labelscnt)*4U*MASKORGROUP) {
4465 				syslog(LOG_NOTICE,"CLTOMA_SCLASS_CREATE - wrong size (%"PRIu32":nleng=%"PRIu8":labels C=%"PRIu8";K=%"PRIu8";A=%"PRIu8")",length,nleng,create_labelscnt,keep_labelscnt,arch_labelscnt);
4466 				eptr->mode = KILL;
4467 				return;
4468 			}
4469 			for (i = 0 ; i < create_labelscnt*MASKORGROUP ; i++) {
4470 				create_labelmasks[i] = get32bit(&data);
4471 			}
4472 			for (i = 0 ; i < keep_labelscnt*MASKORGROUP ; i++) {
4473 				keep_labelmasks[i] = get32bit(&data);
4474 			}
4475 			for (i = 0 ; i < arch_labelscnt*MASKORGROUP ; i++) {
4476 				arch_labelmasks[i] = get32bit(&data);
4477 			}
4478 			status = sclass_create_entry(nleng,name,admin_only,mode,create_labelscnt,create_labelmasks,keep_labelscnt,keep_labelmasks,arch_labelscnt,arch_labelmasks,arch_delay);
4479 		} else {
4480 			status = MFS_ERROR_EINVAL;
4481 		}
4482 	} else {
4483 		status = MFS_ERROR_EPERM_NOTADMIN;
4484 	}
4485 	ptr = matoclserv_createpacket(eptr,MATOCL_SCLASS_CREATE,5);
4486 	put32bit(&ptr,msgid);
4487 	put8bit(&ptr,status);
4488 }
4489 
matoclserv_sclass_change(matoclserventry * eptr,const uint8_t * data,uint32_t length)4490 void matoclserv_sclass_change(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
4491 	uint32_t msgid;
4492 	uint8_t nleng;
4493 	uint8_t fver;
4494 	uint8_t i;
4495 	uint16_t chgmask;
4496 	uint32_t create_labelmasks[9*MASKORGROUP];
4497 	uint32_t keep_labelmasks[9*MASKORGROUP];
4498 	uint32_t arch_labelmasks[9*MASKORGROUP];
4499 	uint8_t mode;
4500 	uint8_t create_labelscnt;
4501 	uint8_t keep_labelscnt;
4502 	uint8_t arch_labelscnt;
4503 	uint16_t arch_delay;
4504 	uint8_t admin_only;
4505 	const uint8_t *name;
4506 	uint8_t *ptr;
4507 	uint8_t status;
4508 
4509 	if (length<5U) {
4510 		syslog(LOG_NOTICE,"CLTOMA_SCLASS_CHANGE - wrong size (%"PRIu32")",length);
4511 		eptr->mode = KILL;
4512 		return;
4513 	}
4514 	msgid = get32bit(&data);
4515 	nleng = get8bit(&data);
4516 	name = data;
4517 	data += nleng;
4518 	if (length<6U+nleng) {
4519 		syslog(LOG_NOTICE,"CLTOMA_SCLASS_CHANGE - wrong size (%"PRIu32":nleng=%"PRIu8")",length,nleng);
4520 		eptr->mode = KILL;
4521 		return;
4522 	}
4523 	create_labelscnt = 0; // silence cppcheck false warnings
4524 	keep_labelscnt = 0; // silence cppcheck false warnings
4525 	arch_labelscnt = 0; // silence cppcheck false warnings
4526 	fver = get8bit(&data);
4527 	if (fver==0) {
4528 		if (length<15U+nleng) {
4529 			syslog(LOG_NOTICE,"CLTOMA_SCLASS_CHANGE - wrong size (%"PRIu32":nleng=%"PRIu8")",length,nleng);
4530 			eptr->mode = KILL;
4531 			return;
4532 		}
4533 		chgmask = get16bit(&data);
4534 		if (sessions_get_sesflags(eptr->sesdata)&SESFLAG_ADMIN || chgmask==0) {
4535 			admin_only = get8bit(&data);
4536 			mode = get8bit(&data);
4537 			arch_delay = get16bit(&data);
4538 			create_labelscnt = get8bit(&data);
4539 			keep_labelscnt = get8bit(&data);
4540 			arch_labelscnt = get8bit(&data);
4541 			if (length!=15U+nleng+(create_labelscnt+keep_labelscnt+arch_labelscnt)*4U*MASKORGROUP) {
4542 				syslog(LOG_NOTICE,"CLTOMA_SCLASS_CHANGE - wrong size (%"PRIu32":nleng=%"PRIu8":labels C=%"PRIu8";K=%"PRIu8";A=%"PRIu8")",length,nleng,create_labelscnt,keep_labelscnt,arch_labelscnt);
4543 				eptr->mode = KILL;
4544 				return;
4545 			}
4546 			for (i = 0 ; i < create_labelscnt*MASKORGROUP ; i++) {
4547 				create_labelmasks[i] = get32bit(&data);
4548 			}
4549 			for (i = 0 ; i < keep_labelscnt*MASKORGROUP ; i++) {
4550 				keep_labelmasks[i] = get32bit(&data);
4551 			}
4552 			for (i = 0 ; i < arch_labelscnt*MASKORGROUP ; i++) {
4553 				arch_labelmasks[i] = get32bit(&data);
4554 			}
4555 			status = sclass_change_entry(nleng,name,chgmask,&admin_only,&mode,&create_labelscnt,create_labelmasks,&keep_labelscnt,keep_labelmasks,&arch_labelscnt,arch_labelmasks,&arch_delay);
4556 		} else {
4557 			status = MFS_ERROR_EPERM_NOTADMIN;
4558 		}
4559 	} else {
4560 		status = MFS_ERROR_EINVAL;
4561 	}
4562 	ptr = matoclserv_createpacket(eptr,MATOCL_SCLASS_CHANGE,(status!=MFS_STATUS_OK)?5:(12U+4U*MASKORGROUP*(create_labelscnt+keep_labelscnt+arch_labelscnt)));
4563 	put32bit(&ptr,msgid);
4564 	if (status!=MFS_STATUS_OK) {
4565 		put8bit(&ptr,status);
4566 	} else {
4567 		put8bit(&ptr,0); // fver
4568 		put8bit(&ptr,admin_only);
4569 		put8bit(&ptr,mode);
4570 		put16bit(&ptr,arch_delay);
4571 		put8bit(&ptr,create_labelscnt);
4572 		put8bit(&ptr,keep_labelscnt);
4573 		put8bit(&ptr,arch_labelscnt);
4574 		for (i = 0 ; i < create_labelscnt*MASKORGROUP ; i++) {
4575 			put32bit(&ptr,create_labelmasks[i]);
4576 		}
4577 		for (i = 0 ; i < keep_labelscnt*MASKORGROUP ; i++) {
4578 			put32bit(&ptr,keep_labelmasks[i]);
4579 		}
4580 		for (i = 0 ; i < arch_labelscnt*MASKORGROUP ; i++) {
4581 			put32bit(&ptr,arch_labelmasks[i]);
4582 		}
4583 	}
4584 }
4585 
matoclserv_sclass_delete(matoclserventry * eptr,const uint8_t * data,uint32_t length)4586 void matoclserv_sclass_delete(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
4587 	uint32_t msgid;
4588 	uint8_t nleng;
4589 	const uint8_t *name;
4590 	uint8_t *ptr;
4591 	uint8_t status;
4592 
4593 	if (length<5) {
4594 		syslog(LOG_NOTICE,"CLTOMA_SCLASS_DELETE - wrong size (%"PRIu32")",length);
4595 		eptr->mode = KILL;
4596 		return;
4597 	}
4598 	msgid = get32bit(&data);
4599 	if (sessions_get_sesflags(eptr->sesdata)&SESFLAG_ADMIN) {
4600 		nleng = get8bit(&data);
4601 		name = data;
4602 		data += nleng;
4603 		if (length!=5U+nleng) {
4604 			syslog(LOG_NOTICE,"CLTOMA_SCLASS_DELETE - wrong size (%"PRIu32":nleng=%"PRIu8")",length,nleng);
4605 			eptr->mode = KILL;
4606 			return;
4607 		}
4608 		status = sclass_delete_entry(nleng,name);
4609 	} else {
4610 		status = MFS_ERROR_EPERM_NOTADMIN;
4611 	}
4612 	ptr = matoclserv_createpacket(eptr,MATOCL_SCLASS_DELETE,5);
4613 	put32bit(&ptr,msgid);
4614 	put8bit(&ptr,status);
4615 }
4616 
matoclserv_sclass_duplicate(matoclserventry * eptr,const uint8_t * data,uint32_t length)4617 void matoclserv_sclass_duplicate(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
4618 	uint32_t msgid;
4619 	uint8_t snleng,dnleng;
4620 	const uint8_t *sname,*dname;
4621 	uint8_t *ptr;
4622 	uint8_t status;
4623 
4624 	if (length<5) {
4625 		syslog(LOG_NOTICE,"CLTOMA_SCLASS_DUPLICATE - wrong size (%"PRIu32")",length);
4626 		eptr->mode = KILL;
4627 		return;
4628 	}
4629 	msgid = get32bit(&data);
4630 	if (sessions_get_sesflags(eptr->sesdata)&SESFLAG_ADMIN) {
4631 		snleng = get8bit(&data);
4632 		sname = data;
4633 		data += snleng;
4634 		if (length<6U+snleng) {
4635 			syslog(LOG_NOTICE,"CLTOMA_SCLASS_DUPLICATE - wrong size (%"PRIu32":snleng=%"PRIu8")",length,snleng);
4636 			eptr->mode = KILL;
4637 			return;
4638 		}
4639 		dnleng = get8bit(&data);
4640 		dname = data;
4641 		data += dnleng;
4642 		if (length!=6U+snleng+dnleng) {
4643 			syslog(LOG_NOTICE,"CLTOMA_SCLASS_DUPLICATE - wrong size (%"PRIu32":snleng=%"PRIu8":dnleng=%"PRIu8")",length,snleng,dnleng);
4644 			eptr->mode = KILL;
4645 			return;
4646 		}
4647 		status = sclass_duplicate_entry(snleng,sname,dnleng,dname);
4648 	} else {
4649 		status = MFS_ERROR_EPERM_NOTADMIN;
4650 	}
4651 	ptr = matoclserv_createpacket(eptr,MATOCL_SCLASS_DUPLICATE,5);
4652 	put32bit(&ptr,msgid);
4653 	put8bit(&ptr,status);
4654 }
4655 
matoclserv_sclass_rename(matoclserventry * eptr,const uint8_t * data,uint32_t length)4656 void matoclserv_sclass_rename(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
4657 	uint32_t msgid;
4658 	uint8_t snleng,dnleng;
4659 	const uint8_t *sname,*dname;
4660 	uint8_t *ptr;
4661 	uint8_t status;
4662 
4663 	if (length<5) {
4664 		syslog(LOG_NOTICE,"CLTOMA_SCLASS_RENAME - wrong size (%"PRIu32")",length);
4665 		eptr->mode = KILL;
4666 		return;
4667 	}
4668 	msgid = get32bit(&data);
4669 	if (sessions_get_sesflags(eptr->sesdata)&SESFLAG_ADMIN) {
4670 		snleng = get8bit(&data);
4671 		sname = data;
4672 		data += snleng;
4673 		if (length<6U+snleng) {
4674 			syslog(LOG_NOTICE,"CLTOMA_SCLASS_RENAME - wrong size (%"PRIu32":snleng=%"PRIu8")",length,snleng);
4675 			eptr->mode = KILL;
4676 			return;
4677 		}
4678 		dnleng = get8bit(&data);
4679 		dname = data;
4680 		data += dnleng;
4681 		if (length!=6U+snleng+dnleng) {
4682 			syslog(LOG_NOTICE,"CLTOMA_SCLASS_RENAME - wrong size (%"PRIu32":snleng=%"PRIu8":dnleng=%"PRIu8")",length,snleng,dnleng);
4683 			eptr->mode = KILL;
4684 			return;
4685 		}
4686 		status = sclass_rename_entry(snleng,sname,dnleng,dname);
4687 	} else {
4688 		status = MFS_ERROR_EPERM_NOTADMIN;
4689 	}
4690 	ptr = matoclserv_createpacket(eptr,MATOCL_SCLASS_RENAME,5);
4691 	put32bit(&ptr,msgid);
4692 	put8bit(&ptr,status);
4693 }
4694 
matoclserv_sclass_list(matoclserventry * eptr,const uint8_t * data,uint32_t length)4695 void matoclserv_sclass_list(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
4696 	uint32_t msgid;
4697 	uint8_t *ptr;
4698 	uint32_t rsize;
4699 	uint8_t longmode;
4700 
4701 	if (length!=5) {
4702 		syslog(LOG_NOTICE,"CLTOMA_SCLASS_LIST - wrong size (%"PRIu32")",length);
4703 		eptr->mode = KILL;
4704 		return;
4705 	}
4706 	msgid = get32bit(&data);
4707 	longmode = get8bit(&data);
4708 	rsize = sclass_list_entries(NULL,longmode);
4709 	ptr = matoclserv_createpacket(eptr,MATOCL_SCLASS_LIST,4+rsize);
4710 	put32bit(&ptr,msgid);
4711 	sclass_list_entries(ptr,longmode);
4712 }
4713 
matoclserv_fuse_getdirstats_old(matoclserventry * eptr,const uint8_t * data,uint32_t length)4714 void matoclserv_fuse_getdirstats_old(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
4715 	uint32_t inode,inodes,files,dirs,chunks;
4716 	uint64_t leng,size,rsize;
4717 	uint32_t msgid;
4718 	uint8_t *ptr;
4719 	uint8_t status;
4720 	if (length!=8) {
4721 		syslog(LOG_NOTICE,"CLTOMA_FUSE_GETDIRSTATS - wrong size (%"PRIu32"/8)",length);
4722 		eptr->mode = KILL;
4723 		return;
4724 	}
4725 	msgid = get32bit(&data);
4726 	inode = get32bit(&data);
4727 	status = fs_get_dir_stats(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,&inodes,&dirs,&files,&chunks,&leng,&size,&rsize);
4728 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_GETDIRSTATS,(status!=MFS_STATUS_OK)?5:60);
4729 	put32bit(&ptr,msgid);
4730 	if (status!=MFS_STATUS_OK) {
4731 		put8bit(&ptr,status);
4732 	} else {
4733 		put32bit(&ptr,inodes);
4734 		put32bit(&ptr,dirs);
4735 		put32bit(&ptr,files);
4736 		put32bit(&ptr,0);
4737 		put32bit(&ptr,0);
4738 		put32bit(&ptr,chunks);
4739 		put32bit(&ptr,0);
4740 		put32bit(&ptr,0);
4741 		put64bit(&ptr,leng);
4742 		put64bit(&ptr,size);
4743 		put64bit(&ptr,rsize);
4744 	}
4745 }
4746 
matoclserv_fuse_getdirstats(matoclserventry * eptr,const uint8_t * data,uint32_t length)4747 void matoclserv_fuse_getdirstats(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
4748 	uint32_t inode,inodes,files,dirs,chunks;
4749 	uint64_t leng,size,rsize;
4750 	uint32_t msgid;
4751 	uint8_t *ptr;
4752 	uint8_t status;
4753 	if (length!=8) {
4754 		syslog(LOG_NOTICE,"CLTOMA_FUSE_GETDIRSTATS - wrong size (%"PRIu32"/8)",length);
4755 		eptr->mode = KILL;
4756 		return;
4757 	}
4758 	msgid = get32bit(&data);
4759 	inode = get32bit(&data);
4760 	status = fs_get_dir_stats(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,&inodes,&dirs,&files,&chunks,&leng,&size,&rsize);
4761 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_GETDIRSTATS,(status!=MFS_STATUS_OK)?5:44);
4762 	put32bit(&ptr,msgid);
4763 	if (status!=MFS_STATUS_OK) {
4764 		put8bit(&ptr,status);
4765 	} else {
4766 		put32bit(&ptr,inodes);
4767 		put32bit(&ptr,dirs);
4768 		put32bit(&ptr,files);
4769 		put32bit(&ptr,chunks);
4770 		put64bit(&ptr,leng);
4771 		put64bit(&ptr,size);
4772 		put64bit(&ptr,rsize);
4773 	}
4774 }
4775 
matoclserv_fuse_gettrash(matoclserventry * eptr,const uint8_t * data,uint32_t length)4776 void matoclserv_fuse_gettrash(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
4777 	uint32_t msgid;
4778 	uint8_t *ptr;
4779 	uint8_t status;
4780 	uint32_t dleng;
4781 	uint32_t tid;
4782 	if (length!=4 && length!=8) {
4783 		syslog(LOG_NOTICE,"CLTOMA_FUSE_GETTRASH - wrong size (%"PRIu32"/4)",length);
4784 		eptr->mode = KILL;
4785 		return;
4786 	}
4787 	msgid = get32bit(&data);
4788 	if (length==8) {
4789 		tid = get32bit(&data);
4790 	} else {
4791 		tid = 0xFFFFFFFF;
4792 	}
4793 	status = fs_readtrash_size(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),tid,&dleng);
4794 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_GETTRASH,(status!=MFS_STATUS_OK)?5:(4+dleng));
4795 	put32bit(&ptr,msgid);
4796 	if (status!=MFS_STATUS_OK) {
4797 		put8bit(&ptr,status);
4798 	} else {
4799 		fs_readtrash_data(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),tid,ptr);
4800 	}
4801 }
4802 
matoclserv_fuse_getdetachedattr(matoclserventry * eptr,const uint8_t * data,uint32_t length)4803 void matoclserv_fuse_getdetachedattr(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
4804 	uint32_t inode;
4805 	uint8_t attr[ATTR_RECORD_SIZE];
4806 	uint32_t msgid;
4807 	uint8_t dtype;
4808 	uint8_t *ptr;
4809 	uint8_t status;
4810 	if (length<8 || length>9) {
4811 		syslog(LOG_NOTICE,"CLTOMA_FUSE_GETDETACHEDATTR - wrong size (%"PRIu32"/8,9)",length);
4812 		eptr->mode = KILL;
4813 		return;
4814 	}
4815 	msgid = get32bit(&data);
4816 	inode = get32bit(&data);
4817 	if (length==9) {
4818 		dtype = get8bit(&data);
4819 	} else {
4820 		dtype = DTYPE_UNKNOWN;
4821 	}
4822 	status = fs_getdetachedattr(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,attr,dtype);
4823 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_GETDETACHEDATTR,(status!=MFS_STATUS_OK)?5:(eptr->asize+4));
4824 	put32bit(&ptr,msgid);
4825 	if (status!=MFS_STATUS_OK) {
4826 		put8bit(&ptr,status);
4827 	} else {
4828 		memcpy(ptr,attr,eptr->asize);
4829 	}
4830 }
4831 
matoclserv_fuse_gettrashpath(matoclserventry * eptr,const uint8_t * data,uint32_t length)4832 void matoclserv_fuse_gettrashpath(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
4833 	uint32_t inode;
4834 	uint32_t pleng;
4835 	const uint8_t *path;
4836 	uint32_t msgid;
4837 	uint8_t *ptr;
4838 	uint8_t status;
4839 	if (length!=8) {
4840 		syslog(LOG_NOTICE,"CLTOMA_FUSE_GETTRASHPATH - wrong size (%"PRIu32"/8)",length);
4841 		eptr->mode = KILL;
4842 		return;
4843 	}
4844 	msgid = get32bit(&data);
4845 	inode = get32bit(&data);
4846 	status = fs_gettrashpath(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,&pleng,&path);
4847 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_GETTRASHPATH,(status!=MFS_STATUS_OK)?5:8+pleng+1);
4848 	put32bit(&ptr,msgid);
4849 	if (status!=MFS_STATUS_OK) {
4850 		put8bit(&ptr,status);
4851 	} else {
4852 		put32bit(&ptr,pleng+1);
4853 		if (pleng>0) {
4854 			memcpy(ptr,path,pleng);
4855 		}
4856 		ptr[pleng]=0;
4857 	}
4858 }
4859 
matoclserv_fuse_settrashpath(matoclserventry * eptr,const uint8_t * data,uint32_t length)4860 void matoclserv_fuse_settrashpath(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
4861 	uint32_t inode;
4862 	const uint8_t *path;
4863 	uint32_t pleng;
4864 	uint32_t msgid;
4865 	uint8_t status;
4866 	uint8_t *ptr;
4867 	if (length<12) {
4868 		syslog(LOG_NOTICE,"CLTOMA_FUSE_SETTRASHPATH - wrong size (%"PRIu32"/>=12)",length);
4869 		eptr->mode = KILL;
4870 		return;
4871 	}
4872 	msgid = get32bit(&data);
4873 	inode = get32bit(&data);
4874 	pleng = get32bit(&data);
4875 	if (length!=12+pleng) {
4876 		syslog(LOG_NOTICE,"CLTOMA_FUSE_SETTRASHPATH - wrong size (%"PRIu32"/%"PRIu32")",length,12+pleng);
4877 		eptr->mode = KILL;
4878 		return;
4879 	}
4880 	path = data;
4881 	data += pleng;
4882 	while (pleng>0 && path[pleng-1]==0) {
4883 		pleng--;
4884 	}
4885 	status = fs_settrashpath(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode,pleng,path);
4886 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_SETTRASHPATH,5);
4887 	put32bit(&ptr,msgid);
4888 	put8bit(&ptr,status);
4889 }
4890 
matoclserv_fuse_undel(matoclserventry * eptr,const uint8_t * data,uint32_t length)4891 void matoclserv_fuse_undel(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
4892 	uint32_t inode;
4893 	uint32_t msgid;
4894 	uint8_t status;
4895 	uint8_t *ptr;
4896 	if (length!=8) {
4897 		syslog(LOG_NOTICE,"CLTOMA_FUSE_UNDEL - wrong size (%"PRIu32"/8)",length);
4898 		eptr->mode = KILL;
4899 		return;
4900 	}
4901 	msgid = get32bit(&data);
4902 	inode = get32bit(&data);
4903 	status = fs_undel(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode);
4904 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_UNDEL,5);
4905 	put32bit(&ptr,msgid);
4906 	put8bit(&ptr,status);
4907 }
4908 
matoclserv_fuse_purge(matoclserventry * eptr,const uint8_t * data,uint32_t length)4909 void matoclserv_fuse_purge(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
4910 	uint32_t inode;
4911 	uint32_t msgid;
4912 	uint8_t *ptr;
4913 	uint8_t status;
4914 	if (length!=8) {
4915 		syslog(LOG_NOTICE,"CLTOMA_FUSE_PURGE - wrong size (%"PRIu32"/8)",length);
4916 		eptr->mode = KILL;
4917 		return;
4918 	}
4919 	msgid = get32bit(&data);
4920 	inode = get32bit(&data);
4921 	status = fs_purge(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),inode);
4922 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_PURGE,5);
4923 	put32bit(&ptr,msgid);
4924 	put8bit(&ptr,status);
4925 }
4926 
4927 
matoclserv_fuse_getsustained(matoclserventry * eptr,const uint8_t * data,uint32_t length)4928 void matoclserv_fuse_getsustained(matoclserventry *eptr,const uint8_t *data,uint32_t length) {
4929 	uint32_t msgid;
4930 	uint8_t *ptr;
4931 	uint8_t status;
4932 	uint32_t dleng;
4933 	if (length!=4) {
4934 		syslog(LOG_NOTICE,"CLTOMA_FUSE_GETSUSTAINED - wrong size (%"PRIu32"/4)",length);
4935 		eptr->mode = KILL;
4936 		return;
4937 	}
4938 	msgid = get32bit(&data);
4939 	status = fs_readsustained_size(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),&dleng);
4940 	ptr = matoclserv_createpacket(eptr,MATOCL_FUSE_GETSUSTAINED,(status!=MFS_STATUS_OK)?5:(4+dleng));
4941 	put32bit(&ptr,msgid);
4942 	if (status!=MFS_STATUS_OK) {
4943 		put8bit(&ptr,status);
4944 	} else {
4945 		fs_readsustained_data(sessions_get_rootinode(eptr->sesdata),sessions_get_sesflags(eptr->sesdata),ptr);
4946 	}
4947 }
4948 
matoclserv_beforedisconnect(matoclserventry * eptr)4949 void matoclserv_beforedisconnect(matoclserventry *eptr) {
4950 	swchunks *swc,**pswc;
4951 	lwchunks *lwc,**plwc;
4952 	uint32_t i;
4953 
4954 	for (i=0 ; i<CHUNKHASHSIZE ; i++) {
4955 		pswc = swchunkshash + i;
4956 		while ((swc = *pswc)) {
4957 			if (swc->eptr == eptr) {
4958 				fs_rollback(swc->inode,swc->indx,swc->prevchunkid,swc->chunkid);
4959 				*pswc = swc->next;
4960 				free(swc);
4961 			} else {
4962 				pswc = &(swc->next);
4963 			}
4964 		}
4965 		plwc = lwchunkshashhead + i;
4966 		while ((lwc = *plwc)) {
4967 			if (lwc->eptr == eptr) {
4968 				*plwc = lwc->next;
4969 				free(lwc);
4970 			} else {
4971 				plwc = &(lwc->next);
4972 			}
4973 		}
4974 		lwchunkshashtail[i] = plwc;
4975 	}
4976 	if (eptr->path!=NULL) {
4977 		free(eptr->path);
4978 		eptr->path = NULL;
4979 	}
4980 	if (eptr->info!=NULL) {
4981 		free(eptr->info);
4982 		eptr->info = NULL;
4983 	}
4984 	sessions_disconnection(eptr->sesdata);
4985 }
4986 
matoclserv_gotpacket(matoclserventry * eptr,uint32_t type,const uint8_t * data,uint32_t length)4987 void matoclserv_gotpacket(matoclserventry *eptr,uint32_t type,const uint8_t *data,uint32_t length) {
4988 	if (type==ANTOAN_NOP) {
4989 		return;
4990 	}
4991 	if (type==ANTOAN_UNKNOWN_COMMAND) { // for future use
4992 		return;
4993 	}
4994 	if (type==ANTOAN_BAD_COMMAND_SIZE) { // for future use
4995 		return;
4996 	}
4997 //	printf("AQQ\n");
4998 	if (eptr->registered==0) {	// unregistered clients - beware that in this context sesdata is NULL
4999 		switch (type) {
5000 			case ANTOAN_GET_VERSION:
5001 				matoclserv_get_version(eptr,data,length);
5002 				break;
5003 			case ANTOAN_GET_CONFIG:
5004 				matoclserv_get_config(eptr,data,length);
5005 				break;
5006 			case CLTOMA_FUSE_REGISTER:
5007 //				printf("REGISTER\n");
5008 				matoclserv_fuse_register(eptr,data,length);
5009 				break;
5010 			case CLTOMA_CSERV_LIST:
5011 				matoclserv_cserv_list(eptr,data,length);
5012 				break;
5013 			case CLTOMA_SESSION_LIST:
5014 				matoclserv_session_list(eptr,data,length);
5015 				break;
5016 			case CLTOAN_CHART:
5017 				matoclserv_chart(eptr,data,length);
5018 				break;
5019 			case CLTOAN_CHART_DATA:
5020 				matoclserv_chart_data(eptr,data,length);
5021 				break;
5022 			case CLTOAN_MONOTONIC_DATA:
5023 				matoclserv_monotonic_data(eptr,data,length);
5024 				break;
5025 			case CLTOMA_INFO:
5026 				matoclserv_info(eptr,data,length);
5027 				break;
5028 			case CLTOMA_FSTEST_INFO:
5029 				matoclserv_fstest_info(eptr,data,length);
5030 				break;
5031 			case CLTOMA_CHUNKSTEST_INFO:
5032 				matoclserv_chunkstest_info(eptr,data,length);
5033 				break;
5034 			case CLTOMA_CHUNKS_MATRIX:
5035 				matoclserv_chunks_matrix(eptr,data,length);
5036 				break;
5037 			case CLTOMA_QUOTA_INFO:
5038 				matoclserv_quota_info(eptr,data,length);
5039 				break;
5040 			case CLTOMA_EXPORTS_INFO:
5041 				matoclserv_exports_info(eptr,data,length);
5042 				break;
5043 			case CLTOMA_MLOG_LIST:
5044 				matoclserv_mlog_list(eptr,data,length);
5045 				break;
5046 			case CLTOMA_CSSERV_COMMAND:
5047 				matoclserv_cserv_command(eptr,data,length);
5048 				break;
5049 			case CLTOMA_SESSION_COMMAND:
5050 				matoclserv_session_command(eptr,data,length);
5051 				break;
5052 			case CLTOMA_MEMORY_INFO:
5053 				matoclserv_memory_info(eptr,data,length);
5054 				break;
5055 			case CLTOAN_MODULE_INFO:
5056 				matoclserv_module_info(eptr,data,length);
5057 				break;
5058 			case CLTOMA_LIST_OPEN_FILES:
5059 				matoclserv_list_open_files(eptr,data,length);
5060 				break;
5061 			case CLTOMA_LIST_ACQUIRED_LOCKS:
5062 				matoclserv_list_acquired_locks(eptr,data,length);
5063 				break;
5064 			case CLTOMA_MASS_RESOLVE_PATHS:
5065 				matoclserv_mass_resolve_paths(eptr,data,length);
5066 				break;
5067 			case CLTOMA_SCLASS_INFO:
5068 				matoclserv_sclass_info(eptr,data,length);
5069 				break;
5070 			case CLTOMA_MISSING_CHUNKS:
5071 				matoclserv_missing_chunks(eptr,data,length);
5072 				break;
5073 			case CLTOMA_NODE_INFO:
5074 				matoclserv_node_info(eptr,data,length);
5075 				break;
5076 			default:
5077 				syslog(LOG_NOTICE,"main master server module: got unknown message from unregistered (type:%"PRIu32")",type);
5078 				eptr->mode=KILL;
5079 		}
5080 	} else if (eptr->registered<100) {	// mounts and new tools
5081 		if (eptr->sesdata==NULL) {
5082 			syslog(LOG_ERR,"registered connection without sesdata !!!");
5083 			eptr->mode=KILL;
5084 			return;
5085 		}
5086 		switch (type) {
5087 			case ANTOAN_GET_VERSION:
5088 				matoclserv_get_version(eptr,data,length);
5089 				break;
5090 			case ANTOAN_GET_CONFIG:
5091 				matoclserv_get_config(eptr,data,length);
5092 				break;
5093 			case CLTOMA_FUSE_REGISTER:
5094 				matoclserv_fuse_register(eptr,data,length);
5095 				break;
5096 			case CLTOMA_FUSE_SUSTAINED_INODES_DEPRECATED:
5097 			case CLTOMA_FUSE_SUSTAINED_INODES:
5098 				matoclserv_fuse_sustained_inodes(eptr,data,length);
5099 				break;
5100 			case CLTOMA_FUSE_AMTIME_INODES:
5101 				matoclserv_fuse_amtime_inodes(eptr,data,length);
5102 				break;
5103 			case CLTOMA_FUSE_TIME_SYNC:
5104 				matoclserv_fuse_time_sync(eptr,data,length);
5105 				break;
5106 			case CLTOMA_FUSE_STATFS:
5107 				matoclserv_fuse_statfs(eptr,data,length);
5108 				break;
5109 			case CLTOMA_FUSE_ACCESS:
5110 				matoclserv_fuse_access(eptr,data,length);
5111 				break;
5112 			case CLTOMA_FUSE_LOOKUP:
5113 				matoclserv_fuse_lookup(eptr,data,length);
5114 				break;
5115 			case CLTOMA_FUSE_GETATTR:
5116 				matoclserv_fuse_getattr(eptr,data,length);
5117 				break;
5118 			case CLTOMA_FUSE_SETATTR:
5119 				matoclserv_fuse_setattr(eptr,data,length);
5120 				break;
5121 			case CLTOMA_FUSE_READLINK:
5122 				matoclserv_fuse_readlink(eptr,data,length);
5123 				break;
5124 			case CLTOMA_FUSE_SYMLINK:
5125 				matoclserv_fuse_symlink(eptr,data,length);
5126 				break;
5127 			case CLTOMA_FUSE_MKNOD:
5128 				matoclserv_fuse_mknod(eptr,data,length);
5129 				break;
5130 			case CLTOMA_FUSE_MKDIR:
5131 				matoclserv_fuse_mkdir(eptr,data,length);
5132 				break;
5133 			case CLTOMA_FUSE_UNLINK:
5134 				matoclserv_fuse_unlink(eptr,data,length);
5135 				break;
5136 			case CLTOMA_FUSE_RMDIR:
5137 				matoclserv_fuse_rmdir(eptr,data,length);
5138 				break;
5139 			case CLTOMA_FUSE_RENAME:
5140 				matoclserv_fuse_rename(eptr,data,length);
5141 				break;
5142 			case CLTOMA_FUSE_LINK:
5143 				matoclserv_fuse_link(eptr,data,length);
5144 				break;
5145 			case CLTOMA_FUSE_READDIR:
5146 				matoclserv_fuse_readdir(eptr,data,length);
5147 				break;
5148 			case CLTOMA_FUSE_OPEN:
5149 				matoclserv_fuse_open(eptr,data,length);
5150 				break;
5151 			case CLTOMA_FUSE_CREATE:
5152 				matoclserv_fuse_create(eptr,data,length);
5153 				break;
5154 			case CLTOMA_FUSE_READ_CHUNK:
5155 				matoclserv_fuse_read_chunk(eptr,data,length);
5156 				break;
5157 			case CLTOMA_FUSE_WRITE_CHUNK:
5158 				matoclserv_fuse_write_chunk(eptr,data,length);
5159 				break;
5160 			case CLTOMA_FUSE_WRITE_CHUNK_END:
5161 				matoclserv_fuse_write_chunk_end(eptr,data,length);
5162 				break;
5163 			case CLTOMA_FUSE_FLOCK:
5164 				matoclserv_fuse_flock(eptr,data,length);
5165 				break;
5166 			case CLTOMA_FUSE_POSIX_LOCK:
5167 				matoclserv_fuse_posix_lock(eptr,data,length);
5168 				break;
5169 // fuse - meta
5170 			case CLTOMA_FUSE_GETTRASH:
5171 				matoclserv_fuse_gettrash(eptr,data,length);
5172 				break;
5173 			case CLTOMA_FUSE_GETDETACHEDATTR:
5174 				matoclserv_fuse_getdetachedattr(eptr,data,length);
5175 				break;
5176 			case CLTOMA_FUSE_GETTRASHPATH:
5177 				matoclserv_fuse_gettrashpath(eptr,data,length);
5178 				break;
5179 			case CLTOMA_FUSE_SETTRASHPATH:
5180 				matoclserv_fuse_settrashpath(eptr,data,length);
5181 				break;
5182 			case CLTOMA_FUSE_UNDEL:
5183 				matoclserv_fuse_undel(eptr,data,length);
5184 				break;
5185 			case CLTOMA_FUSE_PURGE:
5186 				matoclserv_fuse_purge(eptr,data,length);
5187 				break;
5188 			case CLTOMA_FUSE_GETSUSTAINED:
5189 				matoclserv_fuse_getsustained(eptr,data,length);
5190 				break;
5191 			case CLTOMA_FUSE_CHECK:
5192 				matoclserv_fuse_check(eptr,data,length);
5193 				break;
5194 			case CLTOMA_FUSE_GETTRASHTIME:
5195 				matoclserv_fuse_gettrashtime(eptr,data,length);
5196 				break;
5197 			case CLTOMA_FUSE_SETTRASHTIME:
5198 				matoclserv_fuse_settrashtime(eptr,data,length);
5199 				break;
5200 			case CLTOMA_FUSE_GETSCLASS:
5201 				matoclserv_fuse_getsclass(eptr,data,length);
5202 				break;
5203 			case CLTOMA_FUSE_SETSCLASS:
5204 				matoclserv_fuse_setsclass(eptr,data,length);
5205 				break;
5206 			case CLTOMA_FUSE_APPEND_SLICE:
5207 				matoclserv_fuse_append_slice(eptr,data,length);
5208 				break;
5209 			case CLTOMA_FUSE_GETDIRSTATS:
5210 				matoclserv_fuse_getdirstats_old(eptr,data,length);
5211 				break;
5212 			case CLTOMA_FUSE_TRUNCATE:
5213 				matoclserv_fuse_truncate(eptr,data,length);
5214 				break;
5215 			case CLTOMA_FUSE_REPAIR:
5216 				matoclserv_fuse_repair(eptr,data,length);
5217 				break;
5218 			case CLTOMA_FUSE_SNAPSHOT:
5219 				matoclserv_fuse_snapshot(eptr,data,length);
5220 				break;
5221 			case CLTOMA_FUSE_GETEATTR:
5222 				matoclserv_fuse_geteattr(eptr,data,length);
5223 				break;
5224 			case CLTOMA_FUSE_SETEATTR:
5225 				matoclserv_fuse_seteattr(eptr,data,length);
5226 				break;
5227 			case CLTOMA_FUSE_PARENTS:
5228 				matoclserv_fuse_parents(eptr,data,length);
5229 				break;
5230 			case CLTOMA_FUSE_PATHS:
5231 				matoclserv_fuse_paths(eptr,data,length);
5232 				break;
5233 			case CLTOMA_FUSE_GETXATTR:
5234 				matoclserv_fuse_getxattr(eptr,data,length);
5235 				break;
5236 			case CLTOMA_FUSE_SETXATTR:
5237 				matoclserv_fuse_setxattr(eptr,data,length);
5238 				break;
5239 			case CLTOMA_FUSE_GETFACL:
5240 				matoclserv_fuse_getfacl(eptr,data,length);
5241 				break;
5242 			case CLTOMA_FUSE_SETFACL:
5243 				matoclserv_fuse_setfacl(eptr,data,length);
5244 				break;
5245 			case CLTOMA_FUSE_QUOTACONTROL:
5246 				matoclserv_fuse_quotacontrol(eptr,data,length);
5247 				break;
5248 			case CLTOMA_FUSE_ARCHCTL:
5249 				matoclserv_fuse_archctl(eptr,data,length);
5250 				break;
5251 			case CLTOMA_SCLASS_CREATE:
5252 				matoclserv_sclass_create(eptr,data,length);
5253 				break;
5254 			case CLTOMA_SCLASS_CHANGE:
5255 				matoclserv_sclass_change(eptr,data,length);
5256 				break;
5257 			case CLTOMA_SCLASS_DELETE:
5258 				matoclserv_sclass_delete(eptr,data,length);
5259 				break;
5260 			case CLTOMA_SCLASS_DUPLICATE:
5261 				matoclserv_sclass_duplicate(eptr,data,length);
5262 				break;
5263 			case CLTOMA_SCLASS_RENAME:
5264 				matoclserv_sclass_rename(eptr,data,length);
5265 				break;
5266 			case CLTOMA_SCLASS_LIST:
5267 				matoclserv_sclass_list(eptr,data,length);
5268 				break;
5269 
5270 /* for tools - also should be available for registered clients */
5271 			case CLTOMA_CSERV_LIST:
5272 				matoclserv_cserv_list(eptr,data,length);
5273 				break;
5274 			case CLTOMA_SESSION_LIST:
5275 				matoclserv_session_list(eptr,data,length);
5276 				break;
5277 			case CLTOAN_CHART:
5278 				matoclserv_chart(eptr,data,length);
5279 				break;
5280 			case CLTOAN_CHART_DATA:
5281 				matoclserv_chart_data(eptr,data,length);
5282 				break;
5283 			case CLTOAN_MONOTONIC_DATA:
5284 				matoclserv_monotonic_data(eptr,data,length);
5285 				break;
5286 			case CLTOMA_INFO:
5287 				matoclserv_info(eptr,data,length);
5288 				break;
5289 			case CLTOMA_FSTEST_INFO:
5290 				matoclserv_fstest_info(eptr,data,length);
5291 				break;
5292 			case CLTOMA_CHUNKSTEST_INFO:
5293 				matoclserv_chunkstest_info(eptr,data,length);
5294 				break;
5295 			case CLTOMA_CHUNKS_MATRIX:
5296 				matoclserv_chunks_matrix(eptr,data,length);
5297 				break;
5298 			case CLTOMA_QUOTA_INFO:
5299 				matoclserv_quota_info(eptr,data,length);
5300 				break;
5301 			case CLTOMA_EXPORTS_INFO:
5302 				matoclserv_exports_info(eptr,data,length);
5303 				break;
5304 			case CLTOMA_MLOG_LIST:
5305 				matoclserv_mlog_list(eptr,data,length);
5306 				break;
5307 			case CLTOMA_CSSERV_COMMAND:
5308 				matoclserv_cserv_command(eptr,data,length);
5309 				break;
5310 			case CLTOMA_SESSION_COMMAND:
5311 				matoclserv_session_command(eptr,data,length);
5312 				break;
5313 			case CLTOMA_MEMORY_INFO:
5314 				matoclserv_memory_info(eptr,data,length);
5315 				break;
5316 			case CLTOAN_MODULE_INFO:
5317 				matoclserv_module_info(eptr,data,length);
5318 				break;
5319 			case CLTOMA_LIST_OPEN_FILES:
5320 				matoclserv_list_open_files(eptr,data,length);
5321 				break;
5322 			case CLTOMA_LIST_ACQUIRED_LOCKS:
5323 				matoclserv_list_acquired_locks(eptr,data,length);
5324 				break;
5325 			case CLTOMA_MASS_RESOLVE_PATHS:
5326 				matoclserv_mass_resolve_paths(eptr,data,length);
5327 				break;
5328 			case CLTOMA_SCLASS_INFO:
5329 				matoclserv_sclass_info(eptr,data,length);
5330 				break;
5331 			case CLTOMA_MISSING_CHUNKS:
5332 				matoclserv_missing_chunks(eptr,data,length);
5333 				break;
5334 			case CLTOMA_NODE_INFO:
5335 				matoclserv_node_info(eptr,data,length);
5336 				break;
5337 			default:
5338 				syslog(LOG_NOTICE,"main master server module: got unknown message from mfsmount (type:%"PRIu32")",type);
5339 				eptr->mode=KILL;
5340 		}
5341 	} else {	// old mfstools
5342 		if (eptr->sesdata==NULL) {
5343 			syslog(LOG_ERR,"registered connection (tools) without sesdata !!!");
5344 			eptr->mode=KILL;
5345 			return;
5346 		}
5347 		switch (type) {
5348 // extra (external tools)
5349 			case ANTOAN_GET_VERSION:
5350 				matoclserv_get_version(eptr,data,length);
5351 				break;
5352 			case ANTOAN_GET_CONFIG:
5353 				matoclserv_get_config(eptr,data,length);
5354 				break;
5355 			case CLTOMA_FUSE_REGISTER:
5356 				matoclserv_fuse_register(eptr,data,length);
5357 				break;
5358 			case CLTOMA_FUSE_READ_CHUNK:	// used in mfsfileinfo
5359 				matoclserv_fuse_read_chunk(eptr,data,length);
5360 				break;
5361 			case CLTOMA_FUSE_CHECK:
5362 				matoclserv_fuse_check(eptr,data,length);
5363 				break;
5364 			case CLTOMA_FUSE_GETTRASHTIME:
5365 				matoclserv_fuse_gettrashtime(eptr,data,length);
5366 				break;
5367 			case CLTOMA_FUSE_SETTRASHTIME:
5368 				matoclserv_fuse_settrashtime(eptr,data,length);
5369 				break;
5370 			case CLTOMA_FUSE_GETSCLASS:
5371 				matoclserv_fuse_getsclass(eptr,data,length);
5372 				break;
5373 			case CLTOMA_FUSE_SETSCLASS:
5374 				matoclserv_fuse_setsclass(eptr,data,length);
5375 				break;
5376 			case CLTOMA_FUSE_APPEND_SLICE:
5377 				matoclserv_fuse_append_slice(eptr,data,length);
5378 				break;
5379 			case CLTOMA_FUSE_GETDIRSTATS:
5380 				matoclserv_fuse_getdirstats(eptr,data,length);
5381 				break;
5382 			case CLTOMA_FUSE_TRUNCATE:
5383 				matoclserv_fuse_truncate(eptr,data,length);
5384 				break;
5385 			case CLTOMA_FUSE_REPAIR:
5386 				matoclserv_fuse_repair(eptr,data,length);
5387 				break;
5388 			case CLTOMA_FUSE_SNAPSHOT:
5389 				matoclserv_fuse_snapshot(eptr,data,length);
5390 				break;
5391 			case CLTOMA_FUSE_GETEATTR:
5392 				matoclserv_fuse_geteattr(eptr,data,length);
5393 				break;
5394 			case CLTOMA_FUSE_SETEATTR:
5395 				matoclserv_fuse_seteattr(eptr,data,length);
5396 				break;
5397 			case CLTOMA_FUSE_QUOTACONTROL:
5398 				matoclserv_fuse_quotacontrol(eptr,data,length);
5399 				break;
5400 			case CLTOMA_FUSE_ARCHCTL:
5401 				matoclserv_fuse_archctl(eptr,data,length);
5402 				break;
5403 			case CLTOMA_SCLASS_CREATE:
5404 				matoclserv_sclass_create(eptr,data,length);
5405 				break;
5406 			case CLTOMA_SCLASS_CHANGE:
5407 				matoclserv_sclass_change(eptr,data,length);
5408 				break;
5409 			case CLTOMA_SCLASS_DELETE:
5410 				matoclserv_sclass_delete(eptr,data,length);
5411 				break;
5412 			case CLTOMA_SCLASS_DUPLICATE:
5413 				matoclserv_sclass_duplicate(eptr,data,length);
5414 				break;
5415 			case CLTOMA_SCLASS_RENAME:
5416 				matoclserv_sclass_rename(eptr,data,length);
5417 				break;
5418 			case CLTOMA_SCLASS_LIST:
5419 				matoclserv_sclass_list(eptr,data,length);
5420 				break;
5421 			default:
5422 				syslog(LOG_NOTICE,"main master server module: got unknown message from mfstools (type:%"PRIu32")",type);
5423 				eptr->mode=KILL;
5424 		}
5425 	}
5426 }
5427 
matoclserv_read(matoclserventry * eptr,double now)5428 void matoclserv_read(matoclserventry *eptr,double now) {
5429 	int32_t i;
5430 	uint32_t type,leng;
5431 	const uint8_t *ptr;
5432 	uint32_t rbleng,rbpos;
5433 	uint8_t err,hup,errmsg;
5434 	static uint8_t *readbuff = NULL;
5435 	static uint32_t readbuffsize = 0;
5436 
5437 	if (eptr == NULL) {
5438 		if (readbuff != NULL) {
5439 			free(readbuff);
5440 		}
5441 		readbuff = NULL;
5442 		readbuffsize = 0;
5443 		return;
5444 	}
5445 
5446 	if (readbuffsize==0) {
5447 		readbuffsize = 65536;
5448 		readbuff = malloc(readbuffsize);
5449 		passert(readbuff);
5450 	}
5451 
5452 	rbleng = 0;
5453 	err = 0;
5454 	hup = 0;
5455 	errmsg = 0;
5456 	for (;;) {
5457 		i = read(eptr->sock,readbuff+rbleng,readbuffsize-rbleng);
5458 		if (i==0) {
5459 			hup = 1;
5460 			break;
5461 		} else if (i<0) {
5462 			if (ERRNO_ERROR) {
5463 				err = 1;
5464 #ifdef ECONNRESET
5465 				if (errno!=ECONNRESET || eptr->registered<100) {
5466 #endif
5467 					errmsg = 1;
5468 #ifdef ECONNRESET
5469 				}
5470 #endif
5471 			}
5472 			break;
5473 		} else {
5474 			stats_brcvd += i;
5475 			rbleng += i;
5476 			if (rbleng==readbuffsize) {
5477 				readbuffsize*=2;
5478 				readbuff = mfsrealloc(readbuff,readbuffsize);
5479 				passert(readbuff);
5480 			} else {
5481 				break;
5482 			}
5483 		}
5484 	}
5485 
5486 	if (rbleng>0) {
5487 		eptr->lastread = now;
5488 	}
5489 
5490 	rbpos = 0;
5491 	while (rbpos<rbleng) {
5492 		if ((rbleng-rbpos)>=eptr->input_bytesleft) {
5493 			memcpy(eptr->input_startptr,readbuff+rbpos,eptr->input_bytesleft);
5494 			i = eptr->input_bytesleft;
5495 		} else {
5496 			memcpy(eptr->input_startptr,readbuff+rbpos,rbleng-rbpos);
5497 			i = rbleng-rbpos;
5498 		}
5499 		rbpos += i;
5500 		eptr->input_startptr+=i;
5501 		eptr->input_bytesleft-=i;
5502 
5503 		if (eptr->input_bytesleft>0) {
5504 			break;
5505 		}
5506 
5507 		if (eptr->input_packet == NULL) {
5508 			ptr = eptr->input_hdr;
5509 			type = get32bit(&ptr);
5510 			leng = get32bit(&ptr);
5511 
5512 			if (leng>MaxPacketSize) {
5513 				syslog(LOG_WARNING,"main master server module: packet too long (%"PRIu32"/%u) ; command:%"PRIu32,leng,MaxPacketSize,type);
5514 				eptr->input_end = 1;
5515 				return;
5516 			}
5517 
5518 			stats_prcvd++;
5519 			eptr->input_packet = malloc(offsetof(in_packetstruct,data)+leng);
5520 			passert(eptr->input_packet);
5521 			eptr->input_packet->next = NULL;
5522 			eptr->input_packet->type = type;
5523 			eptr->input_packet->leng = leng;
5524 
5525 			eptr->input_startptr = eptr->input_packet->data;
5526 			eptr->input_bytesleft = leng;
5527 		}
5528 
5529 		if (eptr->input_bytesleft>0) {
5530 			continue;
5531 		}
5532 
5533 		if (eptr->input_packet != NULL) {
5534 			*(eptr->inputtail) = eptr->input_packet;
5535 			eptr->inputtail = &(eptr->input_packet->next);
5536 			eptr->input_packet = NULL;
5537 			eptr->input_bytesleft = 8;
5538 			eptr->input_startptr = eptr->input_hdr;
5539 		}
5540 	}
5541 
5542 	if (hup) {
5543 		if (eptr->registered>0 && eptr->registered<100) {	// show this message only for standard, registered clients
5544 			syslog(LOG_NOTICE,"connection with client(ip:%u.%u.%u.%u) has been closed by peer",(eptr->peerip>>24)&0xFF,(eptr->peerip>>16)&0xFF,(eptr->peerip>>8)&0xFF,eptr->peerip&0xFF);
5545 		}
5546 		eptr->input_end = 1;
5547 	} else if (err) {
5548 		if (errmsg) {
5549 			mfs_arg_errlog_silent(LOG_NOTICE,"main master server module: (ip:%u.%u.%u.%u) read error",(eptr->peerip>>24)&0xFF,(eptr->peerip>>16)&0xFF,(eptr->peerip>>8)&0xFF,eptr->peerip&0xFF);
5550 		}
5551 		eptr->input_end = 1;
5552 	}
5553 }
5554 
matoclserv_parse(matoclserventry * eptr)5555 void matoclserv_parse(matoclserventry *eptr) {
5556 	in_packetstruct *ipack;
5557 	uint64_t starttime;
5558 	uint64_t currtime;
5559 
5560 	starttime = monotonic_useconds();
5561 	currtime = starttime;
5562 	while (eptr->mode==DATA && (ipack = eptr->inputhead)!=NULL && starttime+10000>currtime) {
5563 		matoclserv_gotpacket(eptr,ipack->type,ipack->data,ipack->leng);
5564 		eptr->inputhead = ipack->next;
5565 		free(ipack);
5566 		if (eptr->inputhead==NULL) {
5567 			eptr->inputtail = &(eptr->inputhead);
5568 		} else {
5569 			currtime = monotonic_useconds();
5570 		}
5571 	}
5572 	if (eptr->mode==DATA && eptr->inputhead==NULL && eptr->input_end) {
5573 		eptr->mode = KILL;
5574 	}
5575 }
5576 
matoclserv_write(matoclserventry * eptr,double now)5577 void matoclserv_write(matoclserventry *eptr,double now) {
5578 	out_packetstruct *opack;
5579 	int32_t i;
5580 #ifdef HAVE_WRITEV
5581 	struct iovec iovtab[100];
5582 	uint32_t iovdata;
5583 	uint32_t leng;
5584 	uint32_t left;
5585 
5586 	for (;;) {
5587 		leng = 0;
5588 		for (iovdata=0,opack=eptr->outputhead ; iovdata<100 && opack!=NULL ; iovdata++,opack=opack->next) {
5589 			iovtab[iovdata].iov_base = opack->startptr;
5590 			iovtab[iovdata].iov_len = opack->bytesleft;
5591 			leng += opack->bytesleft;
5592 		}
5593 		if (iovdata==0) {
5594 			return;
5595 		}
5596 		i = writev(eptr->sock,iovtab,iovdata);
5597 		if (i<0) {
5598 			if (ERRNO_ERROR) {
5599 				mfs_arg_errlog_silent(LOG_NOTICE,"main master server module: (ip:%u.%u.%u.%u) write error",(eptr->peerip>>24)&0xFF,(eptr->peerip>>16)&0xFF,(eptr->peerip>>8)&0xFF,eptr->peerip&0xFF);
5600 				eptr->mode = KILL;
5601 			}
5602 			return;
5603 		}
5604 		if (i>0) {
5605 			eptr->lastwrite = now;
5606 		}
5607 		stats_bsent+=i;
5608 		left = i;
5609 		while (left>0 && eptr->outputhead!=NULL) {
5610 			opack = eptr->outputhead;
5611 			if (opack->bytesleft>left) {
5612 				opack->startptr+=left;
5613 				opack->bytesleft-=left;
5614 				left = 0;
5615 			} else {
5616 				left -= opack->bytesleft;
5617 				eptr->outputhead = opack->next;
5618 				if (eptr->outputhead==NULL) {
5619 					eptr->outputtail = &(eptr->outputhead);
5620 				}
5621 				free(opack);
5622 				stats_psent++;
5623 			}
5624 		}
5625 		if ((uint32_t)i < leng) {
5626 			return;
5627 		}
5628 	}
5629 #else
5630 	for (;;) {
5631 		opack = eptr->outputhead;
5632 		if (opack==NULL) {
5633 			return;
5634 		}
5635 		i=write(eptr->sock,opack->startptr,opack->bytesleft);
5636 		if (i<0) {
5637 			if (ERRNO_ERROR) {
5638 				mfs_arg_errlog_silent(LOG_NOTICE,"main master server module: (ip:%u.%u.%u.%u) write error",(eptr->peerip>>24)&0xFF,(eptr->peerip>>16)&0xFF,(eptr->peerip>>8)&0xFF,eptr->peerip&0xFF);
5639 				eptr->mode = KILL;
5640 			}
5641 			return;
5642 		}
5643 		if (i>0) {
5644 			eptr->lastwrite = now;
5645 		}
5646 		opack->startptr+=i;
5647 		opack->bytesleft-=i;
5648 		stats_bsent+=i;
5649 		if (opack->bytesleft>0) {
5650 			return;
5651 		}
5652 		stats_psent++;
5653 		eptr->outputhead = opack->next;
5654 		if (eptr->outputhead==NULL) {
5655 			eptr->outputtail = &(eptr->outputhead);
5656 		}
5657 		free(opack);
5658 	}
5659 #endif
5660 }
5661 
matoclserv_desc(struct pollfd * pdesc,uint32_t * ndesc)5662 void matoclserv_desc(struct pollfd *pdesc,uint32_t *ndesc) {
5663 	uint32_t pos = *ndesc;
5664 	matoclserventry *eptr;
5665 
5666 	pdesc[pos].fd = lsock;
5667 		pdesc[pos].events = POLLIN;
5668 		lsockpdescpos = pos;
5669 		pos++;
5670 //		FD_SET(lsock,rset);
5671 //		max = lsock;
5672 	for (eptr=matoclservhead ; eptr ; eptr=eptr->next) {
5673 		pdesc[pos].fd = eptr->sock;
5674 		pdesc[pos].events = 0;
5675 		eptr->pdescpos = pos;
5676 //		i=eptr->sock;
5677 		pdesc[pos].events |= POLLIN;
5678 //			FD_SET(i,rset);
5679 //			if (i>max) {
5680 //				max=i;
5681 //			}
5682 		if (eptr->outputhead!=NULL) {
5683 			pdesc[pos].events |= POLLOUT;
5684 //			FD_SET(i,wset);
5685 //			if (i>max) {
5686 //				max=i;
5687 //			}
5688 		}
5689 		pos++;
5690 	}
5691 	*ndesc = pos;
5692 //	return max;
5693 }
5694 
matoclserv_disconnection_loop(void)5695 void matoclserv_disconnection_loop(void) {
5696 	matoclserventry *eptr,**kptr;
5697 	in_packetstruct *ipptr,*ipaptr;
5698 	out_packetstruct *opptr,*opaptr;
5699 
5700 	kptr = &matoclservhead;
5701 	while ((eptr=*kptr)) {
5702 		if (eptr->mode == KILL) {
5703 			matoclserv_beforedisconnect(eptr);
5704 			tcpclose(eptr->sock);
5705 			if (eptr->input_packet) {
5706 				free(eptr->input_packet);
5707 			}
5708 			ipptr = eptr->inputhead;
5709 			while (ipptr) {
5710 				ipaptr = ipptr;
5711 				ipptr = ipptr->next;
5712 				free(ipaptr);
5713 			}
5714 			opptr = eptr->outputhead;
5715 			while (opptr) {
5716 				opaptr = opptr;
5717 				opptr = opptr->next;
5718 				free(opaptr);
5719 			}
5720 			*kptr = eptr->next;
5721 			free(eptr);
5722 		} else {
5723 			kptr = &(eptr->next);
5724 		}
5725 	}
5726 }
5727 
matoclserv_serve(struct pollfd * pdesc)5728 void matoclserv_serve(struct pollfd *pdesc) {
5729 	double now;
5730 	matoclserventry *eptr;
5731 	int ns;
5732 	static double lastaction = 0.0;
5733 	double timeoutadd;
5734 
5735 	now = monotonic_seconds();
5736 // timeout fix
5737 	if (lastaction>0.0) {
5738 		timeoutadd = now-lastaction;
5739 		if (timeoutadd>1.0) {
5740 			for (eptr=matoclservhead ; eptr ; eptr=eptr->next) {
5741 				eptr->lastread += timeoutadd;
5742 			}
5743 		}
5744 	}
5745 	lastaction = now;
5746 
5747 	if (lsockpdescpos>=0 && (pdesc[lsockpdescpos].revents & POLLIN)) {
5748 //	if (FD_ISSET(lsock,rset)) {
5749 		ns=tcpaccept(lsock);
5750 		if (ns<0) {
5751 			mfs_errlog_silent(LOG_NOTICE,"main master server module: accept error");
5752 		} else {
5753 			tcpnonblock(ns);
5754 			tcpnodelay(ns);
5755 			eptr = malloc(sizeof(matoclserventry));
5756 			passert(eptr);
5757 			eptr->next = matoclservhead;
5758 			matoclservhead = eptr;
5759 			eptr->sock = ns;
5760 			eptr->pdescpos = -1;
5761 			tcpgetpeer(ns,&(eptr->peerip),NULL);
5762 			eptr->registered = 0;
5763 			eptr->version = 0;
5764 			eptr->asize = 0;
5765 			eptr->mode = DATA;
5766 			eptr->lastread = now;
5767 			eptr->lastwrite = now;
5768 			eptr->input_bytesleft = 8;
5769 			eptr->input_startptr = eptr->input_hdr;
5770 			eptr->input_end = 0;
5771 			eptr->input_packet = NULL;
5772 			eptr->inputhead = NULL;
5773 			eptr->inputtail = &(eptr->inputhead);
5774 			eptr->outputhead = NULL;
5775 			eptr->outputtail = &(eptr->outputhead);
5776 
5777 			eptr->path = NULL;
5778 			eptr->info = NULL;
5779 			eptr->ileng = 0;
5780 			eptr->usepassword = 0;
5781 
5782 			eptr->sesdata = NULL;
5783 			memset(eptr->passwordrnd,0,32);
5784 		}
5785 	}
5786 
5787 // read
5788 	for (eptr=matoclservhead ; eptr ; eptr=eptr->next) {
5789 		if (eptr->pdescpos>=0) {
5790 			if ((pdesc[eptr->pdescpos].revents & (POLLERR|POLLIN))==POLLIN && eptr->mode!=KILL) {
5791 				matoclserv_read(eptr,now);
5792 			}
5793 			if (pdesc[eptr->pdescpos].revents & (POLLERR|POLLHUP)) {
5794 				eptr->input_end = 1;
5795 			}
5796 		}
5797 		matoclserv_parse(eptr);
5798 	}
5799 
5800 // write
5801 	for (eptr=matoclservhead ; eptr ; eptr=eptr->next) {
5802 		if (eptr->lastwrite+1.0<now && eptr->registered<100 && eptr->outputhead==NULL) {
5803 			uint8_t *ptr = matoclserv_createpacket(eptr,ANTOAN_NOP,4);	// 4 byte length because of 'msgid'
5804 			*((uint32_t*)ptr) = 0;
5805 		}
5806 		if (eptr->pdescpos>=0) {
5807 			if ((((pdesc[eptr->pdescpos].events & POLLOUT)==0 && (eptr->outputhead)) || (pdesc[eptr->pdescpos].revents & POLLOUT)) && eptr->mode!=KILL) {
5808 				matoclserv_write(eptr,now);
5809 			}
5810 		}
5811 		if (eptr->lastread+10.0<now) {
5812 			eptr->mode = KILL;
5813 		}
5814 		if (eptr->mode==FINISH && eptr->outputhead==NULL) {
5815 			eptr->mode = KILL;
5816 		}
5817 	}
5818 
5819 	matoclserv_disconnection_loop();
5820 }
5821 
matoclserv_keep_alive(void)5822 void matoclserv_keep_alive(void) {
5823 	double now;
5824 	matoclserventry *eptr;
5825 
5826 	now = monotonic_seconds();
5827 	for (eptr=matoclservhead ; eptr ; eptr=eptr->next) {
5828 		if (eptr->mode == DATA && eptr->input_end==0) {
5829 			matoclserv_read(eptr,now);
5830 		}
5831 	}
5832 	for (eptr=matoclservhead ; eptr ; eptr=eptr->next) {
5833 		if (eptr->lastwrite+1.0<now && eptr->registered<100 && eptr->outputhead==NULL) {
5834 			uint8_t *ptr = matoclserv_createpacket(eptr,ANTOAN_NOP,4);	// 4 byte length because of 'msgid'
5835 			*((uint32_t*)ptr) = 0;
5836 		}
5837 		if (eptr->mode == DATA && eptr->outputhead) {
5838 			matoclserv_write(eptr,now);
5839 		}
5840 	}
5841 }
5842 
matoclserv_close_lsock(void)5843 void matoclserv_close_lsock(void) { // after fork
5844 	if (lsock>=0) {
5845 		close(lsock);
5846 	}
5847 }
5848 
matoclserv_term(void)5849 void matoclserv_term(void) {
5850 	matoclserventry *eptr,*eaptr;
5851 	in_packetstruct *ipptr,*ipaptr;
5852 	out_packetstruct *opptr,*opaptr;
5853 	swchunks *swc,*swcn;
5854 	lwchunks *lwc,*lwcn;
5855 	uint32_t i;
5856 
5857 	syslog(LOG_NOTICE,"main master server module: closing %s:%s",ListenHost,ListenPort);
5858 	tcpclose(lsock);
5859 
5860 	eptr = matoclservhead;
5861 	while (eptr) {
5862 		if (eptr->input_packet) {
5863 			free(eptr->input_packet);
5864 		}
5865 		ipptr = eptr->inputhead;
5866 		while (ipptr) {
5867 			ipaptr = ipptr;
5868 			ipptr = ipptr->next;
5869 			free(ipaptr);
5870 		}
5871 		opptr = eptr->outputhead;
5872 		while (opptr) {
5873 			opaptr = opptr;
5874 			opptr = opptr->next;
5875 			free(opaptr);
5876 		}
5877 		eaptr = eptr;
5878 		eptr = eptr->next;
5879 		free(eaptr);
5880 	}
5881 	matoclservhead=NULL;
5882 
5883 	for (i=0 ; i<CHUNKHASHSIZE ; i++) {
5884 		for (swc = swchunkshash[i] ; swc ; swc = swcn) {
5885 //			fs_rollback(swc->inode,swc->indx,swc->prevchunkid,swc->chunkid);
5886 			swcn = swc->next;
5887 			free(swc);
5888 		}
5889 		for (lwc = lwchunkshashhead[i] ; lwc ; lwc = lwcn) {
5890 			lwcn = lwc->next;
5891 			free(lwc);
5892 		}
5893 		swchunkshash[i] = NULL;
5894 		lwchunkshashhead[i] = NULL;
5895 		lwchunkshashtail[i] = NULL;
5896 	}
5897 
5898 	matoclserv_read(NULL,0.0); // free internal read buffer
5899 	matoclserv_gid_storage(0); // free supplementary groups buffer
5900 
5901 	free(ListenHost);
5902 	free(ListenPort);
5903 }
5904 
matoclserv_no_more_pending_jobs(void)5905 int matoclserv_no_more_pending_jobs(void) {
5906 	matoclserventry *eptr;
5907 	uint32_t i;
5908 	for (eptr=matoclservhead ; eptr ; eptr=eptr->next) {
5909 		if (eptr->outputhead!=NULL) {
5910 			return 0;
5911 		}
5912 	}
5913 	for (i=0 ; i<CHUNKHASHSIZE ; i++) {
5914 		if (swchunkshash[i]!=NULL) {
5915 			return 0;
5916 		}
5917 	}
5918 	return 1;
5919 }
5920 
matoclserv_disconnect_all(void)5921 void matoclserv_disconnect_all(void) {
5922 	matoclserventry *eptr;
5923 	for (eptr=matoclservhead ; eptr ; eptr=eptr->next) {
5924 		eptr->mode = KILL;
5925 	}
5926 	matoclserv_disconnection_loop();
5927 }
5928 
matoclserv_reload(void)5929 void matoclserv_reload(void) {
5930 	char *oldListenHost,*oldListenPort;
5931 	int newlsock;
5932 
5933 	matoclserv_reload_sessions();
5934 
5935 	oldListenHost = ListenHost;
5936 	oldListenPort = ListenPort;
5937 	if (cfg_isdefined("MATOCL_LISTEN_HOST") || cfg_isdefined("MATOCL_LISTEN_PORT") || !(cfg_isdefined("MATOCU_LISTEN_HOST") || cfg_isdefined("MATOCU_LISTEN_PORT"))) {
5938 		ListenHost = cfg_getstr("MATOCL_LISTEN_HOST","*");
5939 		ListenPort = cfg_getstr("MATOCL_LISTEN_PORT",DEFAULT_MASTER_CLIENT_PORT);
5940 	} else {
5941 		ListenHost = cfg_getstr("MATOCU_LISTEN_HOST","*"); // deprecated option
5942 		ListenPort = cfg_getstr("MATOCU_LISTEN_PORT",DEFAULT_MASTER_CLIENT_PORT); // deprecated option
5943 	}
5944 	if (strcmp(oldListenHost,ListenHost)==0 && strcmp(oldListenPort,ListenPort)==0) {
5945 		free(oldListenHost);
5946 		free(oldListenPort);
5947 		mfs_arg_syslog(LOG_NOTICE,"main master server module: socket address hasn't changed (%s:%s)",ListenHost,ListenPort);
5948 		return;
5949 	}
5950 
5951 	newlsock = tcpsocket();
5952 	if (newlsock<0) {
5953 		mfs_errlog(LOG_WARNING,"main master server module: socket address has changed, but can't create new socket");
5954 		free(ListenHost);
5955 		free(ListenPort);
5956 		ListenHost = oldListenHost;
5957 		ListenPort = oldListenPort;
5958 		return;
5959 	}
5960 	tcpnonblock(newlsock);
5961 	tcpnodelay(newlsock);
5962 	tcpreuseaddr(newlsock);
5963 	if (tcpstrlisten(newlsock,ListenHost,ListenPort,100)<0) {
5964 		mfs_arg_errlog(LOG_ERR,"main master server module: socket address has changed, but can't listen on socket (%s:%s)",ListenHost,ListenPort);
5965 		free(ListenHost);
5966 		free(ListenPort);
5967 		ListenHost = oldListenHost;
5968 		ListenPort = oldListenPort;
5969 		tcpclose(newlsock);
5970 		return;
5971 	}
5972 	if (tcpsetacceptfilter(newlsock)<0 && errno!=ENOTSUP) {
5973 		mfs_errlog_silent(LOG_NOTICE,"main master server module: can't set accept filter");
5974 	}
5975 	mfs_arg_syslog(LOG_NOTICE,"main master server module: socket address has changed, now listen on %s:%s",ListenHost,ListenPort);
5976 	free(oldListenHost);
5977 	free(oldListenPort);
5978 	tcpclose(lsock);
5979 	lsock = newlsock;
5980 }
5981 
matoclserv_init(void)5982 int matoclserv_init(void) {
5983 	if (cfg_isdefined("MATOCL_LISTEN_HOST") || cfg_isdefined("MATOCL_LISTEN_PORT") || !(cfg_isdefined("MATOCU_LISTEN_HOST") || cfg_isdefined("MATOCU_LISTEN_HOST"))) {
5984 		ListenHost = cfg_getstr("MATOCL_LISTEN_HOST","*");
5985 		ListenPort = cfg_getstr("MATOCL_LISTEN_PORT",DEFAULT_MASTER_CLIENT_PORT);
5986 	} else {
5987 		fprintf(stderr,"change MATOCU_LISTEN_* option names to MATOCL_LISTEN_* !!!\n");
5988 		ListenHost = cfg_getstr("MATOCU_LISTEN_HOST","*"); // deprecated option
5989 		ListenPort = cfg_getstr("MATOCU_LISTEN_PORT",DEFAULT_MASTER_CLIENT_PORT); // deprecated option
5990 	}
5991 
5992 	CreateFirstChunk = 0;
5993 
5994 	lsock = tcpsocket();
5995 	if (lsock<0) {
5996 		mfs_errlog(LOG_ERR,"main master server module: can't create socket");
5997 		return -1;
5998 	}
5999 	tcpnonblock(lsock);
6000 	tcpnodelay(lsock);
6001 	tcpreuseaddr(lsock);
6002 	if (tcpstrlisten(lsock,ListenHost,ListenPort,100)<0) {
6003 		mfs_arg_errlog(LOG_ERR,"main master server module: can't listen on %s:%s",ListenHost,ListenPort);
6004 		return -1;
6005 	}
6006 	if (tcpsetacceptfilter(lsock)<0 && errno!=ENOTSUP) {
6007 		mfs_errlog_silent(LOG_NOTICE,"main master server module: can't set accept filter");
6008 	}
6009 	mfs_arg_syslog(LOG_NOTICE,"main master server module: listen on %s:%s",ListenHost,ListenPort);
6010 
6011 	matoclservhead = NULL;
6012 
6013 	main_time_register(1,0,matoclserv_timeout_waiting_ops);
6014 	main_reload_register(matoclserv_reload);
6015 	main_destruct_register(matoclserv_term);
6016 	main_poll_register(matoclserv_desc,matoclserv_serve);
6017 	main_keepalive_register(matoclserv_keep_alive);
6018 	return 0;
6019 }
6020