1 /*
2  * Copyright (C) 2016 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 <stdlib.h>
27 #include <string.h>
28 #include <inttypes.h>
29 
30 #include "MFSCommunication.h"
31 #include "sharedpointer.h"
32 #include "filesystem.h"
33 #include "sessions.h"
34 #include "openfiles.h"
35 #include "csdb.h"
36 #include "chunks.h"
37 #include "metadata.h"
38 #include "slogger.h"
39 #include "massert.h"
40 #include "mfsstrerr.h"
41 
42 #define EAT(clptr,fn,vno,c) { \
43 	if (*(clptr)!=(c)) { \
44 		mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": '%c' expected\n",(fn),(vno),(c)); \
45 		return -1; \
46 	} \
47 	(clptr)++; \
48 }
49 
50 #define GETNAME(name,clptr,fn,vno,c) { \
51 	uint32_t _tmp_i; \
52 	char _tmp_c,_tmp_h1,_tmp_h2; \
53 	memset((void*)(name),0,256); \
54 	_tmp_i = 0; \
55 	while ((_tmp_c=*((clptr)++))!=c && _tmp_i<255) { \
56 		if (_tmp_c=='%') { \
57 			_tmp_h1 = *((clptr)++); \
58 			_tmp_h2 = *((clptr)++); \
59 			if (_tmp_h1>='0' && _tmp_h1<='9') { \
60 				_tmp_h1-='0'; \
61 			} else if (_tmp_h1>='A' && _tmp_h1<='F') { \
62 				_tmp_h1-=('A'-10); \
63 			} else { \
64 				mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": hex expected\n",(fn),(vno)); \
65 				return -1; \
66 			} \
67 			if (_tmp_h2>='0' && _tmp_h2<='9') { \
68 				_tmp_h2-='0'; \
69 			} else if (_tmp_h2>='A' && _tmp_h2<='F') { \
70 				_tmp_h2-=('A'-10); \
71 			} else { \
72 				mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": hex expected\n",(fn),(vno)); \
73 				return -1; \
74 			} \
75 			_tmp_c = _tmp_h1*16+_tmp_h2; \
76 		} \
77 		name[_tmp_i++] = _tmp_c; \
78 	} \
79 	(clptr)--; \
80 	name[_tmp_i]=0; \
81 }
82 
83 #define GETPATH(path,size,clptr,fn,vno,c) { \
84 	uint32_t _tmp_i; \
85 	char _tmp_c,_tmp_h1,_tmp_h2; \
86 	_tmp_i = 0; \
87 	while ((_tmp_c=*((clptr)++))!=c) { \
88 		if (_tmp_c=='%') { \
89 			_tmp_h1 = *((clptr)++); \
90 			_tmp_h2 = *((clptr)++); \
91 			if (_tmp_h1>='0' && _tmp_h1<='9') { \
92 				_tmp_h1-='0'; \
93 			} else if (_tmp_h1>='A' && _tmp_h1<='F') { \
94 				_tmp_h1-=('A'-10); \
95 			} else { \
96 				mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": hex expected\n",(fn),(vno)); \
97 				return -1; \
98 			} \
99 			if (_tmp_h2>='0' && _tmp_h2<='9') { \
100 				_tmp_h2-='0'; \
101 			} else if (_tmp_h2>='A' && _tmp_h2<='F') { \
102 				_tmp_h2-=('A'-10); \
103 			} else { \
104 				mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": hex expected\n",(fn),(vno)); \
105 				return -1; \
106 			} \
107 			_tmp_c = _tmp_h1*16+_tmp_h2; \
108 		} \
109 		if ((_tmp_i)>=(size)) { \
110 			(size) = _tmp_i+1000; \
111 			if ((path)==NULL) { \
112 				(path) = malloc(size); \
113 			} else { \
114 				uint8_t *_tmp_path = (path); \
115 				(path) = realloc((path),(size)); \
116 				if ((path)==NULL) { \
117 					free(_tmp_path); \
118 				} \
119 			} \
120 			passert(path); \
121 		} \
122 		(path)[_tmp_i++]=_tmp_c; \
123 	} \
124 	if ((_tmp_i)>=(size)) { \
125 		(size) = _tmp_i+1000; \
126 		if ((path)==NULL) { \
127 			(path) = malloc(size); \
128 		} else { \
129 			uint8_t *_tmp_path = (path); \
130 			(path) = realloc((path),(size)); \
131 			if ((path)==NULL) { \
132 				free(_tmp_path); \
133 			} \
134 		} \
135 		passert(path); \
136 	} \
137 	(clptr)--; \
138 	(path)[_tmp_i]=0; \
139 }
140 
141 #define GETDATA(buff,leng,size,clptr,fn,vno,c) { \
142 	char _tmp_c,_tmp_h1,_tmp_h2; \
143 	(leng) = 0; \
144 	while ((_tmp_c=*((clptr)++))!=c) { \
145 		if (_tmp_c=='%') { \
146 			_tmp_h1 = *((clptr)++); \
147 			_tmp_h2 = *((clptr)++); \
148 			if (_tmp_h1>='0' && _tmp_h1<='9') { \
149 				_tmp_h1-='0'; \
150 			} else if (_tmp_h1>='A' && _tmp_h1<='F') { \
151 				_tmp_h1-=('A'-10); \
152 			} else { \
153 				mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": hex expected\n",(fn),(vno)); \
154 				return -1; \
155 			} \
156 			if (_tmp_h2>='0' && _tmp_h2<='9') { \
157 				_tmp_h2-='0'; \
158 			} else if (_tmp_h2>='A' && _tmp_h2<='F') { \
159 				_tmp_h2-=('A'-10); \
160 			} else { \
161 				mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": hex expected\n",(fn),(vno)); \
162 				return -1; \
163 			} \
164 			_tmp_c = _tmp_h1*16+_tmp_h2; \
165 		} \
166 		if ((leng)>=(size)) { \
167 			(size) = (leng)+1000; \
168 			if ((buff)==NULL) { \
169 				(buff) = malloc(size); \
170 			} else { \
171 				uint8_t *_tmp_buff = (buff); \
172 				(buff) = realloc((buff),(size)); \
173 				if ((buff)==NULL) { \
174 					free(_tmp_buff); \
175 				} \
176 			} \
177 			passert(buff); \
178 		} \
179 		(buff)[(leng)++]=_tmp_c; \
180 	} \
181 	(clptr)--; \
182 }
183 
184 #define GETU8(data,clptr) { \
185 	uint32_t tmp; \
186 	char *eptr; \
187 	tmp=strtoul(clptr,&eptr,10); \
188 	clptr = (const char*)eptr; \
189 	if (tmp>255) { \
190 		return -1; \
191 	} \
192 	(data)=tmp; \
193 }
194 
195 #define GETU16(data,clptr) { \
196 	uint32_t tmp; \
197 	char *eptr; \
198 	tmp=strtoul(clptr,&eptr,10); \
199 	clptr = (const char*)eptr; \
200 	if (tmp>65535) { \
201 		return -1; \
202 	} \
203 	(data)=tmp; \
204 }
205 
206 #define GETU32(data,clptr) { \
207 	char *eptr; \
208 	(data)=strtoul(clptr,&eptr,10); \
209 	clptr = (const char*)eptr; \
210 }
211 
212 #define GETU64(data,clptr) { \
213 	char *eptr; \
214 	(data)=strtoull(clptr,&eptr,10); \
215 	clptr = (const char*)eptr; \
216 }
217 
do_access(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)218 int do_access(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
219 	uint32_t inode;
220 	EAT(ptr,filename,lv,'(');
221 	GETU32(inode,ptr);
222 	EAT(ptr,filename,lv,')');
223 	return fs_mr_access(ts,inode);
224 }
225 
do_append(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)226 int do_append(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
227 	uint32_t inode,inode_src;
228 	EAT(ptr,filename,lv,'(');
229 	GETU32(inode,ptr);
230 	EAT(ptr,filename,lv,',');
231 	GETU32(inode_src,ptr);
232 	EAT(ptr,filename,lv,')');
233 	return fs_mr_append(ts,inode,inode_src);
234 }
235 
do_acquire(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)236 int do_acquire(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
237 	uint32_t inode,cuid;
238 	(void)ts;
239 	EAT(ptr,filename,lv,'(');
240 	GETU32(inode,ptr);
241 	EAT(ptr,filename,lv,',');
242 	GETU32(cuid,ptr);
243 	EAT(ptr,filename,lv,')');
244 	return of_mr_acquire(inode,cuid);
245 }
246 
do_attr(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)247 int do_attr(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
248 	uint32_t inode,mode,uid,gid,atime,mtime;
249 	EAT(ptr,filename,lv,'(');
250 	GETU32(inode,ptr);
251 	EAT(ptr,filename,lv,',');
252 	GETU32(mode,ptr);
253 	EAT(ptr,filename,lv,',');
254 	GETU32(uid,ptr);
255 	EAT(ptr,filename,lv,',');
256 	GETU32(gid,ptr);
257 	EAT(ptr,filename,lv,',');
258 	GETU32(atime,ptr);
259 	EAT(ptr,filename,lv,',');
260 	GETU32(mtime,ptr);
261 	EAT(ptr,filename,lv,')');
262 	return fs_mr_attr(ts,inode,mode,uid,gid,atime,mtime);
263 }
264 
265 /*
266 int do_copy(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
267 	uint32_t inode,parent;
268 	uint8_t name[256];
269 	EAT(ptr,filename,lv,'(');
270 	GETU32(inode,ptr);
271 	EAT(ptr,filename,lv,',');
272 	GETU32(parent,ptr);
273 	EAT(ptr,filename,lv,',');
274 	GETNAME(name,ptr,filename,lv,')');
275 	EAT(ptr,filename,lv,')');
276 	return fs_mr_copy(ts,inode,parent,strlen(name),name);
277 }
278 */
279 
do_create(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)280 int do_create(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
281 	uint32_t parent,uid,gid,rdev,inode;
282 	uint16_t mode,cumask;
283 	uint8_t type,name[256];
284 	EAT(ptr,filename,lv,'(');
285 	GETU32(parent,ptr);
286 	EAT(ptr,filename,lv,',');
287 	GETNAME(name,ptr,filename,lv,',');
288 	EAT(ptr,filename,lv,',');
289 	if (*ptr>='0' && *ptr<='9') {
290 		GETU8(type,ptr);
291 	} else {
292 		type = *ptr;
293 		ptr++;
294 	}
295 	EAT(ptr,filename,lv,',');
296 	GETU16(mode,ptr);
297 	EAT(ptr,filename,lv,',');
298 	if (type<16) {
299 		GETU16(cumask,ptr);
300 		EAT(ptr,filename,lv,',');
301 	} else {
302 		cumask = 0;
303 	}
304 	GETU32(uid,ptr);
305 	EAT(ptr,filename,lv,',');
306 	GETU32(gid,ptr);
307 	EAT(ptr,filename,lv,',');
308 	GETU32(rdev,ptr);
309 	EAT(ptr,filename,lv,')');
310 	EAT(ptr,filename,lv,':');
311 	GETU32(inode,ptr);
312 	return fs_mr_create(ts,parent,strlen((char*)name),name,type,mode,cumask,uid,gid,rdev,inode);
313 }
314 
do_csdbop(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)315 int do_csdbop(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
316 	uint32_t op,ip,port,csid;
317 	(void)ts;
318 	EAT(ptr,filename,lv,'(');
319 	GETU8(op,ptr);
320 	EAT(ptr,filename,lv,',');
321 	GETU32(ip,ptr);
322 	EAT(ptr,filename,lv,',');
323 	GETU16(port,ptr);
324 	EAT(ptr,filename,lv,',');
325 	GETU16(csid,ptr);
326 	EAT(ptr,filename,lv,')');
327 	return csdb_mr_op(op,ip,port,csid);
328 }
329 
330 /* deprecated since version 1.7.25 */
do_csadd(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)331 int do_csadd(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
332 	uint32_t ip,port;
333 	(void)ts;
334 	EAT(ptr,filename,lv,'(');
335 	GETU32(ip,ptr);
336 	EAT(ptr,filename,lv,',');
337 	GETU32(port,ptr);
338 	EAT(ptr,filename,lv,')');
339 	return csdb_mr_csadd(ip,port);
340 }
341 
342 /* deprecated since version 1.7.25 */
do_csdel(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)343 int do_csdel(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
344 	uint32_t ip,port;
345 	(void)ts;
346 	EAT(ptr,filename,lv,'(');
347 	GETU32(ip,ptr);
348 	EAT(ptr,filename,lv,',');
349 	GETU32(port,ptr);
350 	EAT(ptr,filename,lv,')');
351 	return csdb_mr_csdel(ip,port);
352 }
353 
do_chunkadd(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)354 int do_chunkadd(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
355 	uint64_t chunkid;
356 	uint32_t version,lockedto;
357 	(void)ts;
358 	EAT(ptr,filename,lv,'(');
359 	GETU64(chunkid,ptr);
360 	EAT(ptr,filename,lv,',');
361 	GETU32(version,ptr);
362 	EAT(ptr,filename,lv,',');
363 	GETU32(lockedto,ptr);
364 	EAT(ptr,filename,lv,')');
365 	return chunk_mr_chunkadd(chunkid,version,lockedto);
366 }
367 
do_chunkdel(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)368 int do_chunkdel(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
369 	uint64_t chunkid;
370 	uint32_t version;
371 	(void)ts;
372 	EAT(ptr,filename,lv,'(');
373 	GETU64(chunkid,ptr);
374 	EAT(ptr,filename,lv,',');
375 	GETU32(version,ptr);
376 	EAT(ptr,filename,lv,')');
377 	return chunk_mr_chunkdel(chunkid,version);
378 }
379 
do_emptytrash(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)380 int do_emptytrash(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
381 	uint32_t sustainedinodes,freeinodes;
382 	EAT(ptr,filename,lv,'(');
383 	EAT(ptr,filename,lv,')');
384 	EAT(ptr,filename,lv,':');
385 	GETU32(freeinodes,ptr);
386 	EAT(ptr,filename,lv,',');
387 	GETU32(sustainedinodes,ptr);
388 	return fs_mr_emptytrash(ts,freeinodes,sustainedinodes);
389 }
390 
do_emptysustained(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)391 int do_emptysustained(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
392 	uint32_t freeinodes;
393 	EAT(ptr,filename,lv,'(');
394 	EAT(ptr,filename,lv,')');
395 	EAT(ptr,filename,lv,':');
396 	GETU32(freeinodes,ptr);
397 	return fs_mr_emptysustained(ts,freeinodes);
398 }
399 
do_freeinodes(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)400 int do_freeinodes(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
401 	uint32_t sustainedinodes,freeinodes;
402 	EAT(ptr,filename,lv,'(');
403 	EAT(ptr,filename,lv,')');
404 	EAT(ptr,filename,lv,':');
405 	GETU32(freeinodes,ptr);
406 	if (*ptr==',') {
407 		EAT(ptr,filename,lv,',');
408 		GETU32(sustainedinodes,ptr);
409 	} else {
410 		sustainedinodes = 0;
411 	}
412 	return fs_mr_freeinodes(ts,freeinodes,sustainedinodes);
413 }
414 
do_incversion(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)415 int do_incversion(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
416 	uint64_t chunkid;
417 	(void)ts;
418 	EAT(ptr,filename,lv,'(');
419 	GETU64(chunkid,ptr);
420 	EAT(ptr,filename,lv,')');
421 	return fs_mr_incversion(chunkid);
422 }
423 
do_link(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)424 int do_link(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
425 	uint32_t inode,parent;
426 	uint8_t name[256];
427 	EAT(ptr,filename,lv,'(');
428 	GETU32(inode,ptr);
429 	EAT(ptr,filename,lv,',');
430 	GETU32(parent,ptr);
431 	EAT(ptr,filename,lv,',');
432 	GETNAME(name,ptr,filename,lv,')');
433 	EAT(ptr,filename,lv,')');
434 	return fs_mr_link(ts,inode,parent,strlen((char*)name),name);
435 }
436 
do_length(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)437 int do_length(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
438 	uint32_t inode;
439 	uint64_t length;
440 	uint8_t canmodmtime;
441 	EAT(ptr,filename,lv,'(');
442 	GETU32(inode,ptr);
443 	EAT(ptr,filename,lv,',');
444 	GETU64(length,ptr);
445 	if (*ptr==',') {
446 		EAT(ptr,filename,lv,',');
447 		GETU8(canmodmtime,ptr);
448 	} else {
449 		canmodmtime = 1;
450 	}
451 	EAT(ptr,filename,lv,')');
452 	return fs_mr_length(ts,inode,length,canmodmtime);
453 }
454 
do_move(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)455 int do_move(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
456 	uint32_t inode,parent_src,parent_dst;
457 	uint8_t name_src[256],name_dst[256];
458 	EAT(ptr,filename,lv,'(');
459 	GETU32(parent_src,ptr);
460 	EAT(ptr,filename,lv,',');
461 	GETNAME(name_src,ptr,filename,lv,',');
462 	EAT(ptr,filename,lv,',');
463 	GETU32(parent_dst,ptr);
464 	EAT(ptr,filename,lv,',');
465 	GETNAME(name_dst,ptr,filename,lv,')');
466 	EAT(ptr,filename,lv,')');
467 	EAT(ptr,filename,lv,':');
468 	GETU32(inode,ptr);
469 	return fs_mr_move(ts,parent_src,strlen((char*)name_src),name_src,parent_dst,strlen((char*)name_dst),name_dst,inode);
470 }
471 
do_nextchunkid(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)472 int do_nextchunkid(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
473 	uint64_t chunkid;
474 	(void)ts;
475 	EAT(ptr,filename,lv,'(');
476 	GETU64(chunkid,ptr);
477 	EAT(ptr,filename,lv,')');
478 	return chunk_mr_nextchunkid(chunkid);
479 }
480 
do_purge(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)481 int do_purge(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
482 	uint32_t inode;
483 	EAT(ptr,filename,lv,'(');
484 	GETU32(inode,ptr);
485 	EAT(ptr,filename,lv,')');
486 	return fs_mr_purge(ts,inode);
487 }
488 
do_quota(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)489 int do_quota(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
490 	uint32_t inode,stimestamp,sinodes,hinodes;
491 	uint64_t slength,ssize,srealsize;
492 	uint64_t hlength,hsize,hrealsize;
493 	uint32_t flags,exceeded;
494 	EAT(ptr,filename,lv,'(');
495 	GETU32(inode,ptr);
496 	EAT(ptr,filename,lv,',');
497 	GETU32(exceeded,ptr);
498 	EAT(ptr,filename,lv,',');
499 	GETU32(flags,ptr);
500 	EAT(ptr,filename,lv,',');
501 	GETU32(stimestamp,ptr);
502 	EAT(ptr,filename,lv,',');
503 	GETU32(sinodes,ptr);
504 	EAT(ptr,filename,lv,',');
505 	GETU32(hinodes,ptr);
506 	EAT(ptr,filename,lv,',');
507 	GETU64(slength,ptr);
508 	EAT(ptr,filename,lv,',');
509 	GETU64(hlength,ptr);
510 	EAT(ptr,filename,lv,',');
511 	GETU64(ssize,ptr);
512 	EAT(ptr,filename,lv,',');
513 	GETU64(hsize,ptr);
514 	EAT(ptr,filename,lv,',');
515 	GETU64(srealsize,ptr);
516 	EAT(ptr,filename,lv,',');
517 	GETU64(hrealsize,ptr);
518 	EAT(ptr,filename,lv,')');
519 	return fs_mr_quota(ts,inode,exceeded,flags,stimestamp,sinodes,hinodes,slength,hlength,ssize,hsize,srealsize,hrealsize);
520 }
521 
522 /*
523 int do_reinit(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
524 	uint32_t inode,indx;
525 	uint64_t chunkid;
526 	EAT(ptr,filename,lv,'(');
527 	GETU32(inode,ptr);
528 	EAT(ptr,filename,lv,',');
529 	GETU32(indx,ptr);
530 	EAT(ptr,filename,lv,')');
531 	EAT(ptr,filename,lv,':');
532 	GETU64(chunkid,ptr);
533 	return fs_mr_reinit(ts,inode,indx,chunkid);
534 }
535 */
do_release(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)536 int do_release(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
537 	uint32_t inode,cuid;
538 	(void)ts;
539 	EAT(ptr,filename,lv,'(');
540 	GETU32(inode,ptr);
541 	EAT(ptr,filename,lv,',');
542 	GETU32(cuid,ptr);
543 	EAT(ptr,filename,lv,')');
544 	return of_mr_release(inode,cuid);
545 }
546 
do_repair(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)547 int do_repair(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
548 	uint32_t inode,indx;
549 	uint32_t version;
550 	EAT(ptr,filename,lv,'(');
551 	GETU32(inode,ptr);
552 	EAT(ptr,filename,lv,',');
553 	GETU32(indx,ptr);
554 	EAT(ptr,filename,lv,')');
555 	EAT(ptr,filename,lv,':');
556 	GETU32(version,ptr);
557 	return fs_mr_repair(ts,inode,indx,version);
558 }
559 
do_renumedges(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)560 int do_renumedges(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
561 	uint64_t enextedgeid;
562 	(void)ts;
563 	EAT(ptr,filename,lv,'(');
564 	EAT(ptr,filename,lv,')');
565 	EAT(ptr,filename,lv,':');
566 	GETU64(enextedgeid,ptr);
567 	return fs_mr_renumerate_edges(enextedgeid);
568 }
569 /*
570 int do_remove(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
571 	uint32_t inode;
572 	EAT(ptr,filename,lv,'(');
573 	GETU32(inode,ptr);
574 	EAT(ptr,filename,lv,')');
575 	return fs_mr_remove(ts,inode);
576 }
577 */
do_session(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)578 int do_session(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
579 	uint32_t sessionid;
580 	(void)ts;
581 	EAT(ptr,filename,lv,'(');
582 	EAT(ptr,filename,lv,')');
583 	EAT(ptr,filename,lv,':');
584 	GETU32(sessionid,ptr);
585 	return sessions_mr_session(sessionid);
586 }
587 
do_sesadd(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)588 int do_sesadd(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
589 	uint32_t rootinode,sesflags,peerip,sessionid;
590 	uint32_t rootuid,rootgid,mapalluid,mapallgid;
591 	uint32_t mingoal,maxgoal,mintrashtime,maxtrashtime;
592 	static uint8_t *info = NULL;
593 	static uint32_t infosize = 0;
594 
595 	(void)ts;
596 	EAT(ptr,filename,lv,'(');
597 	GETU32(rootinode,ptr);
598 	EAT(ptr,filename,lv,',');
599 	GETU32(sesflags,ptr);
600 	EAT(ptr,filename,lv,',');
601 	GETU32(rootuid,ptr);
602 	EAT(ptr,filename,lv,',');
603 	GETU32(rootgid,ptr);
604 	EAT(ptr,filename,lv,',');
605 	GETU32(mapalluid,ptr);
606 	EAT(ptr,filename,lv,',');
607 	GETU32(mapallgid,ptr);
608 	EAT(ptr,filename,lv,',');
609 	GETU32(mingoal,ptr);
610 	EAT(ptr,filename,lv,',');
611 	GETU32(maxgoal,ptr);
612 	EAT(ptr,filename,lv,',');
613 	GETU32(mintrashtime,ptr);
614 	EAT(ptr,filename,lv,',');
615 	GETU32(maxtrashtime,ptr);
616 	EAT(ptr,filename,lv,',');
617 	GETU32(peerip,ptr);
618 	EAT(ptr,filename,lv,',');
619 	GETPATH(info,infosize,ptr,filename,lv,')');
620 	EAT(ptr,filename,lv,')');
621 	EAT(ptr,filename,lv,':');
622 	GETU32(sessionid,ptr);
623 	return sessions_mr_sesadd(rootinode,sesflags,rootuid,rootgid,mapalluid,mapallgid,mingoal,maxgoal,mintrashtime,maxtrashtime,peerip,info,infosize,sessionid);
624 }
625 
do_sesdel(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)626 int do_sesdel(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
627 	uint32_t sessionid;
628 
629 	(void)ts;
630 	EAT(ptr,filename,lv,'(');
631 	GETU32(sessionid,ptr);
632 	EAT(ptr,filename,lv,')');
633 	return sessions_mr_sesdel(sessionid);
634 }
635 
do_sesdisconnected(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)636 int do_sesdisconnected(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
637 	uint32_t sessionid;
638 
639 	EAT(ptr,filename,lv,'(');
640 	GETU32(sessionid,ptr);
641 	EAT(ptr,filename,lv,')');
642 	return sessions_mr_disconnected(sessionid,ts);
643 }
644 
do_seteattr(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)645 int do_seteattr(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
646 	uint32_t inode,uid,ci,nci,npi;
647 	uint8_t eattr,smode;
648 	EAT(ptr,filename,lv,'(');
649 	GETU32(inode,ptr);
650 	EAT(ptr,filename,lv,',');
651 	GETU32(uid,ptr);
652 	EAT(ptr,filename,lv,',');
653 	GETU32(eattr,ptr);
654 	EAT(ptr,filename,lv,',');
655 	GETU32(smode,ptr);
656 	EAT(ptr,filename,lv,')');
657 	EAT(ptr,filename,lv,':');
658 	GETU32(ci,ptr);
659 	EAT(ptr,filename,lv,',');
660 	GETU32(nci,ptr);
661 	EAT(ptr,filename,lv,',');
662 	GETU32(npi,ptr);
663 	return fs_mr_seteattr(ts,inode,uid,eattr,smode,ci,nci,npi);
664 }
665 
do_setfilechunk(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)666 int do_setfilechunk(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
667 	uint32_t inode,indx;
668 	uint64_t chunkid;
669 	(void)ts;
670 	EAT(ptr,filename,lv,'(');
671 	GETU32(inode,ptr);
672 	EAT(ptr,filename,lv,',');
673 	GETU32(indx,ptr);
674 	EAT(ptr,filename,lv,',');
675 	GETU64(chunkid,ptr);
676 	EAT(ptr,filename,lv,')');
677 	return fs_mr_set_file_chunk(inode,indx,chunkid);
678 }
679 
do_setgoal(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)680 int do_setgoal(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
681 	uint32_t inode,uid,ci,nci,npi;
682 	uint8_t goal,smode;
683 	EAT(ptr,filename,lv,'(');
684 	GETU32(inode,ptr);
685 	EAT(ptr,filename,lv,',');
686 	GETU32(uid,ptr);
687 	EAT(ptr,filename,lv,',');
688 	GETU32(goal,ptr);
689 	EAT(ptr,filename,lv,',');
690 	GETU32(smode,ptr);
691 	EAT(ptr,filename,lv,')');
692 	EAT(ptr,filename,lv,':');
693 	GETU32(ci,ptr);
694 	EAT(ptr,filename,lv,',');
695 	GETU32(nci,ptr);
696 	EAT(ptr,filename,lv,',');
697 	GETU32(npi,ptr);
698 	return fs_mr_setgoal(ts,inode,uid,goal,smode,ci,nci,npi);
699 }
700 
do_setpath(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)701 int do_setpath(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
702 	uint32_t inode;
703 	static uint8_t *path = NULL;
704 	static uint32_t pathsize = 0;
705 	(void)ts;
706 	EAT(ptr,filename,lv,'(');
707 	GETU32(inode,ptr);
708 	EAT(ptr,filename,lv,',');
709 	GETPATH(path,pathsize,ptr,filename,lv,')');
710 	EAT(ptr,filename,lv,')');
711 	return fs_mr_setpath(inode,path);
712 }
713 
do_settrashtime(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)714 int do_settrashtime(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
715 	uint32_t inode,uid,ci,nci,npi;
716 	uint32_t trashtime;
717 	uint8_t smode;
718 	EAT(ptr,filename,lv,'(');
719 	GETU32(inode,ptr);
720 	EAT(ptr,filename,lv,',');
721 	GETU32(uid,ptr);
722 	EAT(ptr,filename,lv,',');
723 	GETU32(trashtime,ptr);
724 	EAT(ptr,filename,lv,',');
725 	GETU32(smode,ptr);
726 	EAT(ptr,filename,lv,')');
727 	EAT(ptr,filename,lv,':');
728 	GETU32(ci,ptr);
729 	EAT(ptr,filename,lv,',');
730 	GETU32(nci,ptr);
731 	EAT(ptr,filename,lv,',');
732 	GETU32(npi,ptr);
733 	return fs_mr_settrashtime(ts,inode,uid,trashtime,smode,ci,nci,npi);
734 }
735 
do_setxattr(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)736 int do_setxattr(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
737 	uint32_t inode,valueleng,mode;
738 	uint8_t name[256];
739 	static uint8_t *value = NULL;
740 	static uint32_t valuesize = 0;
741 	EAT(ptr,filename,lv,'(');
742 	GETU32(inode,ptr);
743 	EAT(ptr,filename,lv,',');
744 	GETNAME(name,ptr,filename,lv,',');
745 	EAT(ptr,filename,lv,',');
746 	GETDATA(value,valueleng,valuesize,ptr,filename,lv,',');
747 	EAT(ptr,filename,lv,',');
748 	GETU32(mode,ptr);
749 	EAT(ptr,filename,lv,')');
750 	return fs_mr_setxattr(ts,inode,strlen((char*)name),name,valueleng,value,mode);
751 }
752 
do_setacl(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)753 int do_setacl(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
754 	uint32_t inode,aclblobleng;
755 	uint8_t acltype,changectime;
756 	uint16_t mode,userperm,groupperm,otherperm,mask,namedusers,namedgroups;
757 	static uint8_t *aclblob = NULL;
758 	static uint32_t aclblobsize = 0;
759 	EAT(ptr,filename,lv,'(');
760 	GETU32(inode,ptr);
761 	EAT(ptr,filename,lv,',');
762 	GETU16(mode,ptr);
763 	EAT(ptr,filename,lv,',');
764 	GETU8(changectime,ptr);
765 	EAT(ptr,filename,lv,',');
766 	GETU8(acltype,ptr);
767 	EAT(ptr,filename,lv,',');
768 	GETU16(userperm,ptr);
769 	EAT(ptr,filename,lv,',');
770 	GETU16(groupperm,ptr);
771 	EAT(ptr,filename,lv,',');
772 	GETU16(otherperm,ptr);
773 	EAT(ptr,filename,lv,',');
774 	GETU16(mask,ptr);
775 	EAT(ptr,filename,lv,',');
776 	GETU16(namedusers,ptr);
777 	EAT(ptr,filename,lv,',');
778 	GETU16(namedgroups,ptr);
779 	EAT(ptr,filename,lv,',');
780 	GETDATA(aclblob,aclblobleng,aclblobsize,ptr,filename,lv,')');
781 	EAT(ptr,filename,lv,')');
782 	if (aclblobleng!=6U*(namedusers+namedgroups)) {
783 		return ERROR_MISMATCH;
784 	}
785 	return fs_mr_setacl(ts,inode,mode,changectime,acltype,userperm,groupperm,otherperm,mask,namedusers,namedgroups,aclblob);
786 }
787 
do_snapshot(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)788 int do_snapshot(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
789 	uint32_t inode,parent,smode,sesflags,uid,gids,umask;
790 	static uint8_t *gid = NULL;
791 	static uint32_t gidsize = 0;
792 	uint32_t gidleng;
793 	uint8_t name[256];
794 	uint8_t mode;
795 	uint32_t i;
796 	EAT(ptr,filename,lv,'(');
797 	GETU32(inode,ptr);
798 	EAT(ptr,filename,lv,',');
799 	GETU32(parent,ptr);
800 	EAT(ptr,filename,lv,',');
801 	GETNAME(name,ptr,filename,lv,',');
802 	EAT(ptr,filename,lv,',');
803 	GETU32(smode,ptr);
804 	EAT(ptr,filename,lv,',');
805 	GETU32(sesflags,ptr);
806 	EAT(ptr,filename,lv,',');
807 	GETU32(uid,ptr);
808 	EAT(ptr,filename,lv,',');
809 	GETU32(gids,ptr);
810 	EAT(ptr,filename,lv,',');
811 	mode = 0;
812 	for (i=0 ; ptr[i] && ptr[i]!=')' ; i++) {
813 		if (ptr[i]<'0' || ptr[i]>'9') {
814 			mode=1;
815 			break;
816 		}
817 	}
818 	if (mode==1) {
819 		GETDATA(gid,gidleng,gidsize,ptr,filename,lv,',');
820 		EAT(ptr,filename,lv,',');
821 		GETU32(umask,ptr);
822 		EAT(ptr,filename,lv,')');
823 		if (gids*4!=gidleng) {
824 			return ERROR_MISMATCH;
825 		}
826 		return fs_mr_snapshot(ts,inode,parent,strlen((char*)name),name,smode,sesflags,uid,gids,(uint32_t*)gid,umask);
827 	} else {
828 		GETU32(umask,ptr);
829 		EAT(ptr,filename,lv,')');
830 		return fs_mr_snapshot(ts,inode,parent,strlen((char*)name),name,smode,sesflags,uid,1,&gids,umask);
831 	}
832 }
833 
do_symlink(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)834 int do_symlink(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
835 	uint32_t parent,uid,gid,inode;
836 	uint8_t name[256];
837 	static uint8_t *path = NULL;
838 	static uint32_t pathsize = 0;
839 	EAT(ptr,filename,lv,'(');
840 	GETU32(parent,ptr);
841 	EAT(ptr,filename,lv,',');
842 	GETNAME(name,ptr,filename,lv,',');
843 	EAT(ptr,filename,lv,',');
844 	GETPATH(path,pathsize,ptr,filename,lv,',');
845 	EAT(ptr,filename,lv,',');
846 	GETU32(uid,ptr);
847 	EAT(ptr,filename,lv,',');
848 	GETU32(gid,ptr);
849 	EAT(ptr,filename,lv,')');
850 	EAT(ptr,filename,lv,':');
851 	GETU32(inode,ptr);
852 	return fs_mr_symlink(ts,parent,strlen((char*)name),name,path,uid,gid,inode);
853 }
854 
do_undel(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)855 int do_undel(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
856 	uint32_t inode;
857 	EAT(ptr,filename,lv,'(');
858 	GETU32(inode,ptr);
859 	EAT(ptr,filename,lv,')');
860 	return fs_mr_undel(ts,inode);
861 }
862 
do_unlink(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)863 int do_unlink(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
864 	uint32_t inode,parent;
865 	uint8_t name[256];
866 	EAT(ptr,filename,lv,'(');
867 	GETU32(parent,ptr);
868 	EAT(ptr,filename,lv,',');
869 	GETNAME(name,ptr,filename,lv,')');
870 	EAT(ptr,filename,lv,')');
871 	EAT(ptr,filename,lv,':');
872 	GETU32(inode,ptr);
873 	return fs_mr_unlink(ts,parent,strlen((char*)name),name,inode);
874 }
875 
do_unlock(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)876 int do_unlock(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
877 	uint64_t chunkid;
878 	(void)ts;
879 	EAT(ptr,filename,lv,'(');
880 	GETU64(chunkid,ptr);
881 	EAT(ptr,filename,lv,')');
882 	return fs_mr_unlock(chunkid);
883 }
884 
do_trunc(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)885 int do_trunc(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
886 	uint32_t inode,indx;
887 	uint64_t chunkid;
888 	EAT(ptr,filename,lv,'(');
889 	GETU32(inode,ptr);
890 	EAT(ptr,filename,lv,',');
891 	GETU32(indx,ptr);
892 	EAT(ptr,filename,lv,')');
893 	EAT(ptr,filename,lv,':');
894 	GETU64(chunkid,ptr);
895 	return fs_mr_trunc(ts,inode,indx,chunkid);
896 }
897 
do_write(const char * filename,uint64_t lv,uint32_t ts,const char * ptr)898 int do_write(const char *filename,uint64_t lv,uint32_t ts,const char *ptr) {
899 	uint32_t inode,indx,opflag;
900 	uint64_t chunkid;
901 	EAT(ptr,filename,lv,'(');
902 	GETU32(inode,ptr);
903 	EAT(ptr,filename,lv,',');
904 	GETU32(indx,ptr);
905 	if (*ptr==',') {
906 		EAT(ptr,filename,lv,',');
907 		GETU32(opflag,ptr);
908 	} else {
909 		opflag=1;
910 	}
911 	EAT(ptr,filename,lv,')');
912 	EAT(ptr,filename,lv,':');
913 	GETU64(chunkid,ptr);
914 	return fs_mr_write(ts,inode,indx,opflag,chunkid);
915 }
916 
917 #define HASHCODESTR(str) (((((uint8_t*)(str))[0]*256U+((uint8_t*)(str))[1])*256U+((uint8_t*)(str))[2])*256U+((uint8_t*)(str))[3])
918 #define HASHCODE(a,b,c,d) (((((uint8_t)a)*256U+(uint8_t)b)*256U+(uint8_t)c)*256U+(uint8_t)d)
919 
restore_line(const char * filename,uint64_t lv,const char * line)920 int restore_line(const char *filename,uint64_t lv,const char *line) {
921 	const char *ptr;
922 	uint32_t ts;
923 	uint32_t hc;
924 	int status;
925 //	char* errormsgs[]={ ERROR_STRINGS };
926 
927 	status = ERROR_MISMATCH;
928 	ptr = line;
929 
930 //	EAT(ptr,filename,lv,':');
931 //	EAT(ptr,filename,lv,' ');
932 	GETU32(ts,ptr);
933 	EAT(ptr,filename,lv,'|');
934 	hc = HASHCODESTR(ptr);
935 	switch (hc) {
936 		case HASHCODE('A','C','C','E'):
937 			if (strncmp(ptr,"ACCESS",6)==0) {
938 				return do_access(filename,lv,ts,ptr+6);
939 			}
940 			break;
941 		case HASHCODE('A','T','T','R'):
942 			return do_attr(filename,lv,ts,ptr+4);
943 		case HASHCODE('A','P','P','E'):
944 			if (strncmp(ptr,"APPEND",6)==0) {
945 				return do_append(filename,lv,ts,ptr+6);
946 			}
947 			break;
948 		case HASHCODE('A','C','Q','U'):
949 			if (strncmp(ptr,"ACQUIRE",7)==0) {
950 				return do_acquire(filename,lv,ts,ptr+7);
951 			}
952 			break;
953 		case HASHCODE('A','Q','U','I'):
954 			if (strncmp(ptr,"AQUIRE",6)==0) {
955 				return do_acquire(filename,lv,ts,ptr+6);
956 			}
957 			break;
958 		case HASHCODE('C','R','E','A'):
959 			if (strncmp(ptr,"CREATE",6)==0) {
960 				return do_create(filename,lv,ts,ptr+6);
961 			}
962 			break;
963 		case HASHCODE('C','H','U','N'):
964 			if (strncmp(ptr,"CHUNKADD",8)==0) {
965 				return do_chunkadd(filename,lv,ts,ptr+8);
966 			} else if (strncmp(ptr,"CHUNKDEL",8)==0) {
967 				return do_chunkdel(filename,lv,ts,ptr+8);
968 			}
969 			break;
970 		case HASHCODE('C','S','D','B'):
971 			if (strncmp(ptr,"CSDBOP",6)==0) {
972 				return do_csdbop(filename,lv,ts,ptr+6);
973 			}
974 			break;
975 		case HASHCODE('C','S','A','D'):
976 			if (strncmp(ptr,"CSADD",5)==0) {		// deprecated
977 				return do_csadd(filename,lv,ts,ptr+5);
978 			}
979 			break;
980 		case HASHCODE('C','S','D','E'):
981 			if (strncmp(ptr,"CSDEL",5)==0) {		// deprecated
982 				return do_csdel(filename,lv,ts,ptr+5);
983 			}
984 			break;
985 		case HASHCODE('C','U','S','T'):
986 			if (strncmp(ptr,"CUSTOMER",8)==0) {	// deprecated
987 				return do_session(filename,lv,ts,ptr+8);
988 			}
989 			break;
990 		case HASHCODE('E','M','P','T'):
991 			if (strncmp(ptr,"EMPTYTRASH",10)==0) {
992 				return do_emptytrash(filename,lv,ts,ptr+10);
993 			} else if (strncmp(ptr,"EMPTYSUSTAINED",14)==0) {
994 				return do_emptysustained(filename,lv,ts,ptr+14);
995 			} else if (strncmp(ptr,"EMPTYRESERVED",13)==0) {
996 				return do_emptysustained(filename,lv,ts,ptr+13);
997 			}
998 			break;
999 		case HASHCODE('F','R','E','E'):
1000 			if (strncmp(ptr,"FREEINODES",10)==0) {
1001 				return do_freeinodes(filename,lv,ts,ptr+10);
1002 			}
1003 			break;
1004 		case HASHCODE('I','N','C','V'):
1005 			if (strncmp(ptr,"INCVERSION",10)==0) {
1006 				return do_incversion(filename,lv,ts,ptr+10);
1007 			}
1008 			break;
1009 		case HASHCODE('L','E','N','G'):
1010 			if (strncmp(ptr,"LENGTH",6)==0) {
1011 				return do_length(filename,lv,ts,ptr+6);
1012 			}
1013 			break;
1014 		case HASHCODE('L','I','N','K'):
1015 			return do_link(filename,lv,ts,ptr+4);
1016 		case HASHCODE('N','E','X','T'):
1017 			if (strncmp(ptr,"NEXTCHUNKID",11)==0) {
1018 				return do_nextchunkid(filename,lv,ts,ptr+11); // deprecated
1019 			}
1020 			break;
1021 		case HASHCODE('M','O','V','E'):
1022 			return do_move(filename,lv,ts,ptr+4);
1023 		case HASHCODE('P','U','R','G'):
1024 			if (strncmp(ptr,"PURGE",5)==0) {
1025 				return do_purge(filename,lv,ts,ptr+5);
1026 			}
1027 			break;
1028 		case HASHCODE('Q','U','O','T'):
1029 			if (strncmp(ptr,"QUOTA",5)==0) {
1030 				return do_quota(filename,lv,ts,ptr+5);
1031 			}
1032 			break;
1033 		case HASHCODE('R','E','L','E'):
1034 			if (strncmp(ptr,"RELEASE",7)==0) {
1035 				return do_release(filename,lv,ts,ptr+7);
1036 			}
1037 			break;
1038 		case HASHCODE('R','E','P','A'):
1039 			if (strncmp(ptr,"REPAIR",6)==0) {
1040 				return do_repair(filename,lv,ts,ptr+6);
1041 			}
1042 			break;
1043 		case HASHCODE('R','E','N','U'):
1044 			if (strncmp(ptr,"RENUMEDGES",10)==0) {
1045 				return do_renumedges(filename,lv,ts,ptr+10);
1046 			}
1047 			break;
1048 		case HASHCODE('S','E','T','E'):
1049 			if (strncmp(ptr,"SETEATTR",8)==0) {
1050 				return do_seteattr(filename,lv,ts,ptr+8);
1051 			}
1052 			break;
1053 		case HASHCODE('S','E','T','F'):
1054 			if (strncmp(ptr,"SETFILECHUNK",12)==0) {
1055 				return do_setfilechunk(filename,lv,ts,ptr+12);
1056 			}
1057 			break;
1058 		case HASHCODE('S','E','T','G'):
1059 			if (strncmp(ptr,"SETGOAL",7)==0) {
1060 				return do_setgoal(filename,lv,ts,ptr+7);
1061 			}
1062 			break;
1063 		case HASHCODE('S','E','T','P'):
1064 			if (strncmp(ptr,"SETPATH",7)==0) {
1065 				return do_setpath(filename,lv,ts,ptr+7);
1066 			}
1067 			break;
1068 		case HASHCODE('S','E','T','T'):
1069 			if (strncmp(ptr,"SETTRASHTIME",12)==0) {
1070 				return do_settrashtime(filename,lv,ts,ptr+12);
1071 			}
1072 			break;
1073 		case HASHCODE('S','E','T','X'):
1074 			if (strncmp(ptr,"SETXATTR",8)==0) {
1075 				return do_setxattr(filename,lv,ts,ptr+8);
1076 			}
1077 			break;
1078 		case HASHCODE('S','E','T','A'):
1079 			if (strncmp(ptr,"SETACL",6)==0) {
1080 				return do_setacl(filename,lv,ts,ptr+6);
1081 			}
1082 			break;
1083 		case HASHCODE('S','N','A','P'):
1084 			if (strncmp(ptr,"SNAPSHOT",8)==0) {
1085 				return do_snapshot(filename,lv,ts,ptr+8);
1086 			}
1087 			break;
1088 		case HASHCODE('S','Y','M','L'):
1089 			if (strncmp(ptr,"SYMLINK",7)==0) {
1090 				return do_symlink(filename,lv,ts,ptr+7);
1091 			}
1092 			break;
1093 		case HASHCODE('S','E','S','S'):
1094 			if (strncmp(ptr,"SESSION",7)==0) { // deprecated
1095 				return do_session(filename,lv,ts,ptr+7);
1096 			}
1097 			break;
1098 		case HASHCODE('S','E','S','A'):
1099 			if (strncmp(ptr,"SESADD",6)==0) {
1100 				return do_sesadd(filename,lv,ts,ptr+6);
1101 			}
1102 			break;
1103 		case HASHCODE('S','E','S','D'):
1104 			if (strncmp(ptr,"SESDEL",6)==0) {
1105 				return do_sesdel(filename,lv,ts,ptr+6);
1106 			} else if (strncmp(ptr,"SESDISCONNECTED",15)==0) {
1107 				return do_sesdisconnected(filename,lv,ts,ptr+15);
1108 			}
1109 			break;
1110 		case HASHCODE('T','R','U','N'):
1111 			if (strncmp(ptr,"TRUNC",5)==0) {
1112 				return do_trunc(filename,lv,ts,ptr+5);
1113 			}
1114 			break;
1115 		case HASHCODE('U','N','L','I'):
1116 			if (strncmp(ptr,"UNLINK",6)==0) {
1117 				return do_unlink(filename,lv,ts,ptr+6);
1118 			}
1119 			break;
1120 		case HASHCODE('U','N','D','E'):
1121 			if (strncmp(ptr,"UNDEL",5)==0) {
1122 				return do_undel(filename,lv,ts,ptr+5);
1123 			}
1124 			break;
1125 		case HASHCODE('U','N','L','O'):
1126 			if (strncmp(ptr,"UNLOCK",6)==0) {
1127 				return do_unlock(filename,lv,ts,ptr+6);
1128 			}
1129 			break;
1130 		case HASHCODE('W','R','I','T'):
1131 			if (strncmp(ptr,"WRITE",5)==0) {
1132 				return do_write(filename,lv,ts,ptr+5);
1133 			}
1134 			break;
1135 	}
1136 	mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": unknown entry '%s'\n",filename,lv,ptr);
1137 #if 0
1138 	switch (*ptr) {
1139 		case 'A':
1140 			if (strncmp(ptr,"ACCESS",6)==0) {
1141 				status = do_access(filename,lv,ts,ptr+6);
1142 			} else if (strncmp(ptr,"ATTR",4)==0) {
1143 				status = do_attr(filename,lv,ts,ptr+4);
1144 			} else if (strncmp(ptr,"APPEND",6)==0) {
1145 				status = do_append(filename,lv,ts,ptr+6);
1146 			} else if (strncmp(ptr,"ACQUIRE",7)==0) {
1147 				status = do_acquire(filename,lv,ts,ptr+7);
1148 			} else if (strncmp(ptr,"AQUIRE",6)==0) {
1149 				status = do_acquire(filename,lv,ts,ptr+6);
1150 			} else {
1151 				mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": unknown entry '%s'\n",filename,lv,ptr);
1152 			}
1153 			break;
1154 		case 'C':
1155 			if (strncmp(ptr,"CREATE",6)==0) {
1156 				status = do_create(filename,lv,ts,ptr+6);
1157 			} else if (strncmp(ptr,"CHUNKADD",8)==0) {
1158 				status = do_chunkadd(filename,lv,ts,ptr+8);
1159 			} else if (strncmp(ptr,"CHUNKDEL",8)==0) {
1160 				status = do_chunkdel(filename,lv,ts,ptr+8);
1161 			} else if (strncmp(ptr,"CSDBOP",6)==0) {
1162 				status = do_csdbop(filename,lv,ts,ptr+6);
1163 			} else if (strncmp(ptr,"CSADD",5)==0) {		// deprecated
1164 				status = do_csadd(filename,lv,ts,ptr+5);
1165 			} else if (strncmp(ptr,"CSDEL",5)==0) {		// deprecated
1166 				status = do_csdel(filename,lv,ts,ptr+5);
1167 			} else if (strncmp(ptr,"CUSTOMER",8)==0) {	// deprecated
1168 				status = do_session(filename,lv,ts,ptr+8);
1169 			} else {
1170 				mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": unknown entry '%s'\n",filename,lv,ptr);
1171 			}
1172 			break;
1173 		case 'E':
1174 			if (strncmp(ptr,"EMPTYTRASH",10)==0) {
1175 				status = do_emptytrash(filename,lv,ts,ptr+10);
1176 			} else if (strncmp(ptr,"EMPTYSUSTAINED",14)==0) {
1177 				status = do_emptysustained(filename,lv,ts,ptr+14);
1178 			} else if (strncmp(ptr,"EMPTYRESERVED",13)==0) {
1179 				status = do_emptysustained(filename,lv,ts,ptr+13);
1180 			} else {
1181 				mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": unknown entry '%s'\n",filename,lv,ptr);
1182 			}
1183 			break;
1184 		case 'F':
1185 			if (strncmp(ptr,"FREEINODES",10)==0) {
1186 				status = do_freeinodes(filename,lv,ts,ptr+10);
1187 			} else {
1188 				mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": unknown entry '%s'\n",filename,lv,ptr);
1189 			}
1190 			break;
1191 		case 'I':
1192 			if (strncmp(ptr,"INCVERSION",10)==0) {
1193 				status = do_incversion(filename,lv,ts,ptr+10);
1194 			} else {
1195 				mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": unknown entry '%s'\n",filename,lv,ptr);
1196 			}
1197 			break;
1198 		case 'L':
1199 			if (strncmp(ptr,"LENGTH",6)==0) {
1200 				status = do_length(filename,lv,ts,ptr+6);
1201 			} else if (strncmp(ptr,"LINK",4)==0) {
1202 				status = do_link(filename,lv,ts,ptr+4);
1203 			} else {
1204 				mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": unknown entry '%s'\n",filename,lv,ptr);
1205 			}
1206 			break;
1207 		case 'N':
1208 			if (strncmp(ptr,"NEXTCHUNKID",11)==0) {
1209 				status = do_nextchunkid(filename,lv,ts,ptr+11); // deprecated
1210 			} else {
1211 				mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": unknown entry '%s'\n",filename,lv,ptr);
1212 			}
1213 		case 'M':
1214 			if (strncmp(ptr,"MOVE",4)==0) {
1215 				status = do_move(filename,lv,ts,ptr+4);
1216 			} else {
1217 				mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": unknown entry '%s'\n",filename,lv,ptr);
1218 			}
1219 			break;
1220 		case 'P':
1221 			if (strncmp(ptr,"PURGE",5)==0) {
1222 				status = do_purge(filename,lv,ts,ptr+5);
1223 			} else {
1224 				mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": unknown entry '%s'\n",filename,lv,ptr);
1225 			}
1226 			break;
1227 		case 'Q':
1228 			if (strncmp(ptr,"QUOTA",5)==0) {
1229 				status = do_quota(filename,lv,ts,ptr+5);
1230 			} else {
1231 				mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": unknown entry '%s'\n",filename,lv,ptr);
1232 			}
1233 			break;
1234 		case 'R':
1235 			if (strncmp(ptr,"RELEASE",7)==0) {
1236 				status = do_release(filename,lv,ts,ptr+7);
1237 			} else if (strncmp(ptr,"REPAIR",6)==0) {
1238 				status = do_repair(filename,lv,ts,ptr+6);
1239 			} else if (strncmp(ptr,"RENUMEDGES",10)==0) {
1240 				status = do_renumedges(filename,lv,ts,ptr+10);
1241 			} else {
1242 				mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": unknown entry '%s'\n",filename,lv,ptr);
1243 			}
1244 			break;
1245 		case 'S':
1246 			if (strncmp(ptr,"SETEATTR",8)==0) {
1247 				status = do_seteattr(filename,lv,ts,ptr+8);
1248 			} else if (strncmp(ptr,"SETGOAL",7)==0) {
1249 				status = do_setgoal(filename,lv,ts,ptr+7);
1250 			} else if (strncmp(ptr,"SETPATH",7)==0) {
1251 				status = do_setpath(filename,lv,ts,ptr+7);
1252 			} else if (strncmp(ptr,"SETTRASHTIME",12)==0) {
1253 				status = do_settrashtime(filename,lv,ts,ptr+12);
1254 			} else if (strncmp(ptr,"SETXATTR",8)==0) {
1255 				status = do_setxattr(filename,lv,ts,ptr+8);
1256 			} else if (strncmp(ptr,"SETACL",6)==0) {
1257 				status = do_setacl(filename,lv,ts,ptr+6);
1258 			} else if (strncmp(ptr,"SNAPSHOT",8)==0) {
1259 				status = do_snapshot(filename,lv,ts,ptr+8);
1260 			} else if (strncmp(ptr,"SYMLINK",7)==0) {
1261 				status = do_symlink(filename,lv,ts,ptr+7);
1262 			} else if (strncmp(ptr,"SESSION",7)==0) { // deprecated
1263 				status = do_session(filename,lv,ts,ptr+7);
1264 			} else if (strncmp(ptr,"SESADD",6)==0) {
1265 				status = do_sesadd(filename,lv,ts,ptr+6);
1266 			} else if (strncmp(ptr,"SESDEL",6)==0) {
1267 				status = do_sesdel(filename,lv,ts,ptr+6);
1268 			} else if (strncmp(ptr,"SESDISCONNECTED",15)==0) {
1269 				status = do_sesdisconnected(filename,lv,ts,ptr+15);
1270 			} else {
1271 				mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": unknown entry '%s'\n",filename,lv,ptr);
1272 			}
1273 			break;
1274 		case 'T':
1275 			if (strncmp(ptr,"TRUNC",5)==0) {
1276 				status = do_trunc(filename,lv,ts,ptr+5);
1277 			} else {
1278 				mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": unknown entry '%s'\n",filename,lv,ptr);
1279 			}
1280 			break;
1281 		case 'U':
1282 			if (strncmp(ptr,"UNLINK",6)==0) {
1283 				status = do_unlink(filename,lv,ts,ptr+6);
1284 			} else if (strncmp(ptr,"UNDEL",5)==0) {
1285 				status = do_undel(filename,lv,ts,ptr+5);
1286 			} else if (strncmp(ptr,"UNLOCK",6)==0) {
1287 				status = do_unlock(filename,lv,ts,ptr+6);
1288 			} else {
1289 				mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": unknown entry '%s'\n",filename,lv,ptr);
1290 			}
1291 			break;
1292 		case 'W':
1293 			if (strncmp(ptr,"WRITE",5)==0) {
1294 				status = do_write(filename,lv,ts,ptr+5);
1295 			} else {
1296 				mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": unknown entry '%s'\n",filename,lv,ptr);
1297 			}
1298 			break;
1299 		default:
1300 			mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": unknown entry '%s'\n",filename,lv,ptr);
1301 	}
1302 #endif
1303 //	if (status>STATUS_OK) {
1304 //		mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": error: %d (%s)\n",filename,lv,status,errormsgs[status]);
1305 //	}
1306 	return status;
1307 }
1308 
restore_net(uint64_t lv,const char * ptr)1309 int restore_net(uint64_t lv,const char *ptr) {
1310 	uint8_t status;
1311 	if (lv!=meta_version()) {
1312 		syslog(LOG_WARNING,"desync - invalid meta version (version in packet: %"PRIu64" / expected: %"PRIu64")",lv,meta_version());
1313 		return -1;
1314 	}
1315 	status = restore_line("NET",lv,ptr);
1316 	if (status!=STATUS_OK) {
1317 		syslog(LOG_WARNING,"desync - operation (%s) error: %d (%s)",ptr,status,mfsstrerr(status));
1318 		return -1;
1319 	}
1320 	if (lv+1!=meta_version()) {
1321 		syslog(LOG_WARNING,"desync - meta version has not been increased after operation (%s)",ptr);
1322 		return -1;
1323 	}
1324 	return 0;
1325 }
1326 
1327 static uint64_t v=0,lastv=0;
1328 static void *lastshfn = NULL;
1329 
restore_file(void * shfilename,uint64_t lv,const char * ptr,uint8_t vlevel)1330 int restore_file(void *shfilename,uint64_t lv,const char *ptr,uint8_t vlevel) {
1331 	int status;
1332 	char *lastfn;
1333 	char *filename = (char*)shp_get(shfilename);
1334 	if (lastv==0 || v==0 || lastshfn==NULL) {
1335 		v = meta_version();
1336 		lastv = lv-1;
1337 		lastfn = "(no file)";
1338 	} else {
1339 		lastfn = (char*)shp_get(lastshfn);
1340 	}
1341 	if (vlevel>1) {
1342 		mfs_arg_syslog(LOG_NOTICE,"filename: %s ; current meta version: %"PRIu64" ; previous changeid: %"PRIu64" ; current changeid: %"PRIu64" ; change data%s",filename,v,lastv,lv,ptr);
1343 	}
1344 	if (lv<lastv) {
1345 		mfs_arg_syslog(LOG_WARNING,"merge error - possibly corrupted input file - ignore entry (filename: %s)\n",filename);
1346 		return 0;
1347 	} else if (lv>=v) {
1348 		if (lv==lastv) {
1349 			if (vlevel>1) {
1350 				mfs_arg_syslog(LOG_WARNING,"duplicated entry: %"PRIu64" (previous file: %s, current file: %s)\n",lv,lastfn,filename);
1351 			}
1352 		} else if (lv>lastv+1) {
1353 			mfs_arg_syslog(LOG_WARNING,"hole in change files (entries from %s:%"PRIu64" to %s:%"PRIu64" are missing) - add more files\n",lastfn,lastv+1,filename,lv-1);
1354 			return -2;
1355 		} else {
1356 			if (vlevel>0) {
1357 				mfs_arg_syslog(LOG_WARNING,"%s: change%s",filename,ptr);
1358 			}
1359 			status = restore_line(filename,lv,ptr);
1360 			if (status<0) { // parse error - just ignore this line
1361 				return 0;
1362 			}
1363 			if (status>0) { // other errors - stop processing data
1364 				mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": operation (%s) error: %d (%s)",filename,lv,ptr,status,mfsstrerr(status));
1365 				return -1;
1366 			}
1367 			v = meta_version();
1368 			if (lv+1!=v) {
1369 				mfs_arg_syslog(LOG_WARNING,"%s:%"PRIu64": version mismatch\n",filename,lv);
1370 				return -1;
1371 			}
1372 		}
1373 	}
1374 	lastv = lv;
1375 	if (shfilename!=lastshfn) {
1376 		shp_inc(shfilename);
1377 		if (lastshfn!=NULL) {
1378 			shp_dec(lastshfn);
1379 		}
1380 		lastshfn = shfilename;
1381 	}
1382 	return 0;
1383 }
1384