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 <string.h>
27 #include <math.h>
28 #include <limits.h>
29 #include <stdlib.h>
30 #include <sys/types.h>
31 #include <sys/param.h>
32 #include <sys/stat.h>
33 #include <sys/statvfs.h>
34 #include <sys/time.h>
35 #include <unistd.h>
36 #include <fcntl.h>
37 #include <inttypes.h>
38 #include <poll.h>
39 #include <errno.h>
40
41 #include "labelparser.h"
42 #include "datapack.h"
43 #include "massert.h"
44 #include "strerr.h"
45 #include "mfsstrerr.h"
46 #include "sockets.h"
47 #include "hashfn.h"
48 #include "liset64.h"
49 #include "clocks.h"
50 #include "md5.h"
51 #include "MFSCommunication.h"
52 #include "idstr.h"
53
54 #include "mfstools_master.h"
55
56 #define tcpread(s,b,l) tcptoread(s,b,l,20000)
57 #define tcpwrite(s,b,l) tcptowrite(s,b,l,20000)
58
59 #define FILEINFO_QUICK 0x01
60 #define FILEINFO_CRC 0x02
61 #define FILEINFO_SIGNATURE 0x04
62
63 #define DIRINFO_INODES 0x01
64 #define DIRINFO_DIRS 0x02
65 #define DIRINFO_FILES 0x04
66 #define DIRINFO_CHUNKS 0x08
67 #define DIRINFO_LENGTH 0x10
68 #define DIRINFO_SIZE 0x20
69 #define DIRINFO_REALSIZE 0x40
70 #define DIRINFO_PRECISE 0x80
71
72 #define INODE_VALUE_MASK 0x1FFFFFFF
73 #define INODE_TYPE_MASK 0x60000000
74 #define INODE_TYPE_TRASH 0x20000000
75 #define INODE_TYPE_SUSTAINED 0x40000000
76 #define INODE_TYPE_SPECIAL 0x00000000
77
78 static const char* eattrtab[EATTR_BITS]={EATTR_STRINGS};
79 static const char* eattrdesc[EATTR_BITS]={EATTR_DESCRIPTIONS};
80
81 static uint8_t humode=0;
82 static uint8_t numbermode=0;
83
84 #define PHN_USESI 0x01
85 #define PHN_USEIEC 0x00
print_humanized_number(const char * format,uint64_t number,uint8_t flags)86 void print_humanized_number(const char *format,uint64_t number,uint8_t flags) {
87 char numbuf[6]; // [ "xxx" , "xx" , "x" , "x.x" ] + ["" , "X" , "Xi"]
88 uint64_t divisor;
89 uint16_t b;
90 uint8_t i;
91 uint8_t scale;
92
93 if (flags & PHN_USESI) {
94 divisor = 1000;
95 } else {
96 divisor = 1024;
97 }
98 if (number>(UINT64_MAX/100)) {
99 number /= divisor;
100 number *= 100;
101 scale = 1;
102 } else {
103 number *= 100;
104 scale = 0;
105 }
106 while (number>=99950) {
107 number /= divisor;
108 scale+=1;
109 }
110 i=0;
111 if (number<995 && scale>0) {
112 b = ((uint32_t)number + 5) / 10;
113 numbuf[i++]=(b/10)+'0';
114 numbuf[i++]='.';
115 numbuf[i++]=(b%10)+'0';
116 } else {
117 b = ((uint32_t)number + 50) / 100;
118 if (b>=100) {
119 numbuf[i++]=(b/100)+'0';
120 b%=100;
121 }
122 if (b>=10 || i>0) {
123 numbuf[i++]=(b/10)+'0';
124 b%=10;
125 }
126 numbuf[i++]=b+'0';
127 }
128 if (scale>0) {
129 if (flags&PHN_USESI) {
130 numbuf[i++]="-kMGTPE"[scale];
131 } else {
132 numbuf[i++]="-KMGTPE"[scale];
133 numbuf[i++]='i';
134 }
135 }
136 numbuf[i++]='\0';
137 printf(format,numbuf);
138 }
139
print_number_only(uint64_t number,uint8_t bytesflag)140 void print_number_only(uint64_t number,uint8_t bytesflag) {
141 if (humode>0) {
142 if (bytesflag) {
143 if (humode==1 || humode==3) {
144 print_humanized_number("%5sB",number,PHN_USEIEC);
145 } else {
146 print_humanized_number("%4sB",number,PHN_USESI);
147 }
148 } else {
149 if (humode==1 || humode==3) {
150 print_humanized_number("%5s",number,PHN_USEIEC);
151 } else {
152 print_humanized_number("%4s",number,PHN_USESI);
153 }
154 }
155 if (humode>2) {
156 printf(" (%"PRIu64")",number);
157 }
158 } else {
159 if (numbermode==0) {
160 printf("%"PRIu64,number);
161 } else if (numbermode==1) {
162 printf("%"PRIu64,number/1024);
163 } else if (numbermode==2) {
164 printf("%"PRIu64,number/(1024*1024));
165 } else if (numbermode==3) {
166 printf("%"PRIu64,number/(1024*1024*1024));
167 }
168 }
169 }
170
print_number(const char * prefix,const char * suffix,uint64_t number,uint8_t mode32,uint8_t bytesflag,uint8_t dflag)171 void print_number(const char *prefix,const char *suffix,uint64_t number,uint8_t mode32,uint8_t bytesflag,uint8_t dflag) {
172 if (prefix) {
173 printf("%s",prefix);
174 }
175 if (dflag) {
176 if (humode>0) {
177 if (bytesflag) {
178 if (humode==1 || humode==3) {
179 print_humanized_number("%5sB",number,PHN_USEIEC);
180 } else {
181 print_humanized_number("%4sB",number,PHN_USESI);
182 }
183 } else {
184 if (humode==1 || humode==3) {
185 print_humanized_number(" %5s",number,PHN_USEIEC);
186 } else {
187 print_humanized_number(" %4s",number,PHN_USESI);
188 }
189 }
190 if (humode>2) {
191 if (mode32) {
192 printf(" (%10"PRIu32")",(uint32_t)number);
193 } else {
194 printf(" (%20"PRIu64")",number);
195 }
196 }
197 } else {
198 if (numbermode==0) {
199 if (mode32) {
200 printf("%10"PRIu32,(uint32_t)number);
201 } else {
202 printf("%20"PRIu64,number);
203 }
204 } else if (numbermode==1) {
205 if (mode32) {
206 printf("%7"PRIu32,((uint32_t)number)/1024);
207 } else {
208 printf("%17"PRIu64,number/1024);
209 }
210 } else if (numbermode==2) {
211 if (mode32) {
212 printf("%4"PRIu32,((uint32_t)number)/(1024*1024));
213 } else {
214 printf("%14"PRIu64,number/(1024*1024));
215 }
216 } else if (numbermode==3) {
217 if (mode32) {
218 printf("%1"PRIu32,((uint32_t)number)/(1024*1024*1024));
219 } else {
220 printf("%11"PRIu64,number/(1024*1024*1024));
221 }
222 }
223 }
224 } else {
225 switch(humode) {
226 case 0:
227 if (numbermode==0) {
228 if (mode32) {
229 printf(" -");
230 } else {
231 printf(" -");
232 }
233 } else if (numbermode==1) {
234 if (mode32) {
235 printf(" -");
236 } else {
237 printf(" -");
238 }
239 } else if (numbermode==2) {
240 if (mode32) {
241 printf(" -");
242 } else {
243 printf(" -");
244 }
245 } else if (numbermode==3) {
246 if (mode32) {
247 printf("-");
248 } else {
249 printf(" -");
250 }
251 }
252 break;
253 case 1:
254 printf(" -");
255 break;
256 case 2:
257 printf(" -");
258 break;
259 case 3:
260 if (mode32) {
261 printf(" -");
262 } else {
263 printf(" -");
264 }
265 break;
266 case 4:
267 if (mode32) {
268 printf(" -");
269 } else {
270 printf(" -");
271 }
272 break;
273 }
274 }
275 if (suffix) {
276 printf("%s",suffix);
277 }
278 }
279
my_get_number(const char * str,uint64_t * ret,uint64_t max,uint8_t bytesflag)280 int my_get_number(const char *str,uint64_t *ret,uint64_t max,uint8_t bytesflag) {
281 uint64_t val,frac,fracdiv;
282 double drval,mult;
283 int f;
284 val=0;
285 frac=0;
286 fracdiv=1;
287 f=0;
288 while (*str>='0' && *str<='9') {
289 f=1;
290 val*=10;
291 val+=(*str-'0');
292 str++;
293 }
294 if (*str=='.') { // accept ".5" (without 0)
295 str++;
296 while (*str>='0' && *str<='9') {
297 fracdiv*=10;
298 frac*=10;
299 frac+=(*str-'0');
300 str++;
301 }
302 if (fracdiv==1) { // if there was '.' expect number afterwards
303 return -1;
304 }
305 } else if (f==0) { // but not empty string
306 return -1;
307 }
308 if (str[0]=='\0' || (bytesflag && str[0]=='B' && str[1]=='\0')) {
309 mult=1.0;
310 } else if (str[0]!='\0' && (str[1]=='\0' || (bytesflag && str[1]=='B' && str[2]=='\0'))) {
311 switch(str[0]) {
312 case 'k':
313 mult=1e3;
314 break;
315 case 'M':
316 mult=1e6;
317 break;
318 case 'G':
319 mult=1e9;
320 break;
321 case 'T':
322 mult=1e12;
323 break;
324 case 'P':
325 mult=1e15;
326 break;
327 case 'E':
328 mult=1e18;
329 break;
330 default:
331 return -1;
332 }
333 } else if (str[0]!='\0' && str[1]=='i' && (str[2]=='\0' || (bytesflag && str[2]=='B' && str[3]=='\0'))) {
334 switch(str[0]) {
335 case 'K':
336 mult=1024.0;
337 break;
338 case 'M':
339 mult=1048576.0;
340 break;
341 case 'G':
342 mult=1073741824.0;
343 break;
344 case 'T':
345 mult=1099511627776.0;
346 break;
347 case 'P':
348 mult=1125899906842624.0;
349 break;
350 case 'E':
351 mult=1152921504606846976.0;
352 break;
353 default:
354 return -1;
355 }
356 } else {
357 return -1;
358 }
359 drval = round(((double)frac/(double)fracdiv+(double)val)*mult);
360 *ret = drval;
361 if (drval>max || ((*ret)==0 && drval>1.0)) { // when max==UINT64_MAX and drval==2^64 then drval>max is false because common type for uint64_t and double is double and we lost precision here - therefore the second condition
362 return -2;
363 }
364 return 1;
365 }
366
bsd_basename(const char * path,char * bname)367 int bsd_basename(const char *path,char *bname) {
368 const char *endp, *startp;
369
370 /* Empty or NULL string gets treated as "." */
371 if (path == NULL || *path == '\0') {
372 (void)strcpy(bname, ".");
373 return 0;
374 }
375
376 /* Strip trailing slashes */
377 endp = path + strlen(path) - 1;
378 while (endp > path && *endp == '/') {
379 endp--;
380 }
381
382 /* All slashes becomes "/" */
383 if (endp == path && *endp == '/') {
384 (void)strcpy(bname, "/");
385 return 0;
386 }
387
388 /* Find the start of the base */
389 startp = endp;
390 while (startp > path && *(startp - 1) != '/') {
391 startp--;
392 }
393 if (endp - startp + 2 > PATH_MAX) {
394 return -1;
395 }
396 (void)strncpy(bname, startp, endp - startp + 1);
397 bname[endp - startp + 1] = '\0';
398 return 0;
399 }
400
bsd_dirname(const char * path,char * bname)401 int bsd_dirname(const char *path,char *bname) {
402 const char *endp;
403
404 /* Empty or NULL string gets treated as "." */
405 if (path == NULL || *path == '\0') {
406 (void)strcpy(bname, ".");
407 return 0;
408 }
409
410 /* Strip trailing slashes */
411 endp = path + strlen(path) - 1;
412 while (endp > path && *endp == '/') {
413 endp--;
414 }
415
416 /* Find the start of the dir */
417 while (endp > path && *endp != '/') {
418 endp--;
419 }
420
421 /* Either the dir is "/" or there are no slashes */
422 if (endp == path) {
423 (void)strcpy(bname, *endp == '/' ? "/" : ".");
424 return 0;
425 } else {
426 do {
427 endp--;
428 } while (endp > path && *endp == '/');
429 }
430
431 if (endp - path + 2 > PATH_MAX) {
432 return -1;
433 }
434 (void)strncpy(bname, path, endp - path + 1);
435 bname[endp - path + 1] = '\0';
436 return 0;
437 }
438
dirname_inplace(char * path)439 void dirname_inplace(char *path) {
440 char *endp;
441
442 if (path==NULL) {
443 return;
444 }
445 if (path[0]=='\0') {
446 path[0]='.';
447 path[1]='\0';
448 return;
449 }
450
451 /* Strip trailing slashes */
452 endp = path + strlen(path) - 1;
453 while (endp > path && *endp == '/') {
454 endp--;
455 }
456
457 /* Find the start of the dir */
458 while (endp > path && *endp != '/') {
459 endp--;
460 }
461
462 if (endp == path) {
463 if (path[0]=='/') {
464 path[1]='\0';
465 } else {
466 path[0]='.';
467 path[1]='\0';
468 }
469 return;
470 } else {
471 *endp = '\0';
472 }
473 }
474
475 int inode_liset;
476 int chunk_liset;
477
478 /* ---- INODE QUEUE ---- */
479
480 typedef struct _inoqueue {
481 uint32_t inode;
482 struct _inoqueue *next;
483 } inoqueue;
484
485 static inoqueue *qhead,**qtail;
486
sc_dequeue(uint32_t * inode)487 uint8_t sc_dequeue(uint32_t *inode) {
488 inoqueue *iq;
489 if (qhead==NULL) {
490 return 0;
491 } else {
492 iq = qhead;
493 qhead = iq->next;
494 if (qhead==NULL) {
495 qtail = &qhead;
496 }
497 *inode = iq->inode;
498 free(iq);
499 return 1;
500 }
501 }
502
sc_enqueue(uint32_t inode)503 uint8_t sc_enqueue(uint32_t inode) {
504 inoqueue *iq;
505 if (liset_addval(inode_liset,inode)==0) { // new element
506 iq = malloc(sizeof(inoqueue));
507 iq->inode = inode;
508 iq->next = NULL;
509 *qtail = iq;
510 qtail = &(iq->next);
511 return 1;
512 } else {
513 return 0;
514 }
515 }
516
parse_slice_expr(char * p,int64_t * slice_from,int64_t * slice_to)517 static inline int parse_slice_expr(char *p,int64_t *slice_from,int64_t *slice_to) {
518 if (*p==':') {
519 *slice_from = 0;
520 p++;
521 } else {
522 *slice_from = strtoll(p,&p,10);
523 if (*p!=':') {
524 return -1;
525 }
526 p++;
527 }
528 if (*p=='\0') {
529 *slice_to = 0x80000000;
530 } else {
531 *slice_to = strtoll(p,&p,10);
532 }
533 if (*p!='\0') {
534 return -1;
535 }
536 return 0;
537 }
538
539 // formats:
540 // # - number of seconds
541 // #s - number of seconds
542 // #.#m - number of minutes
543 // #.#h - number of hours
544 // #.#d - number of days
545 // #.#w - number of weeks
parse_period(char * str,char ** endpos)546 static inline uint32_t parse_period(char *str,char **endpos) {
547 double base;
548 double divisor;
549 base = 0.0;
550 while ((*str)>='0' && (*str)<='9') {
551 base *= 10.0;
552 base += (*str)-'0';
553 str++;
554 }
555 if ((*str)=='.') {
556 divisor = 0.1;
557 str++;
558 while ((*str)>='0' && (*str)<='9') {
559 base += ((*str)-'0')*divisor;
560 divisor /= 10.0;
561 str++;
562 }
563 }
564 while ((*str)==' ') {
565 str++;
566 }
567 if ((*str)=='s') {
568 str++;
569 } else if ((*str)=='m') {
570 str++;
571 base *= 60.0;
572 } else if ((*str)=='h') {
573 str++;
574 base *= 3600.0;
575 } else if ((*str)=='d') {
576 str++;
577 base *= 86400.0;
578 } else if ((*str)=='w') {
579 str++;
580 base *= 604800.0;
581 }
582 *endpos = str;
583 if (base >= UINT32_MAX) {
584 return UINT32_MAX;
585 }
586 if (base <= 0) {
587 return 0;
588 }
589 return base;
590 }
591
file_paths(const char * fname)592 int file_paths(const char* fname) {
593 const char *p;
594 struct stat st;
595 char cwdbuff[MAXPATHLEN];
596 uint32_t arginode;
597 uint32_t inode;
598 uint32_t leng,pleng;
599
600 p = fname;
601 while (*p>='0' && *p<='9') {
602 p++;
603 }
604
605 if (*p=='\0' && stat(fname,&st)<0 && errno==ENOENT) {
606 arginode = strtoul(fname,NULL,10);
607 p = getcwd(cwdbuff,MAXPATHLEN);
608 if (master_prepare_conn(p,&inode,NULL,NULL,0,0)<0) {
609 return -1;
610 }
611 inode = arginode;
612 } else {
613 if (master_prepare_conn(fname,&inode,NULL,NULL,0,0)<0) {
614 return -1;
615 }
616 }
617 master_new_packet();
618 master_put32bit(inode);
619 if (master_send_and_receive(CLTOMA_FUSE_PATHS,MATOCL_FUSE_PATHS)<0) {
620 return -1;
621 }
622 leng = master_get_leng();
623 if (leng==1) {
624 printf("%s: %s\n",fname,mfsstrerr(master_get8bit()));
625 return -1;
626 }
627 printf("%s:\n",fname);
628 while (leng>=4) {
629 pleng = master_get32bit();
630 leng-=4;
631 if (leng>=pleng) {
632 while (pleng) {
633 putchar(master_get8bit());
634 pleng--;
635 leng--;
636 }
637 putchar('\n');
638 } else {
639 leng=0;
640 }
641 }
642 if (master_end_packet()==0) {
643 printf("%s: master query: packet size error\n",fname);
644 return -1;
645 }
646 return 0;
647 }
648
649 typedef struct _storage_class {
650 uint8_t admin_only;
651 uint8_t mode;
652 uint16_t arch_delay;
653 uint8_t create_labelscnt,keep_labelscnt,arch_labelscnt;
654 uint32_t create_labelmasks[9][MASKORGROUP];
655 uint32_t keep_labelmasks[9][MASKORGROUP];
656 uint32_t arch_labelmasks[9][MASKORGROUP];
657 } storage_class;
658
deserialize_sc(storage_class * sc)659 static inline int deserialize_sc(storage_class *sc) {
660 uint8_t i,og;
661 sc->admin_only = master_get8bit();
662 sc->mode = master_get8bit();
663 sc->arch_delay = master_get16bit();
664 sc->create_labelscnt = master_get8bit();
665 sc->keep_labelscnt = master_get8bit();
666 sc->arch_labelscnt = master_get8bit();
667 if (sc->create_labelscnt>9 || sc->create_labelscnt<1 || sc->keep_labelscnt>9 || sc->keep_labelscnt<1 || sc->arch_labelscnt>9 || sc->arch_labelscnt<1) {
668 return -1;
669 }
670 for (i=0 ; i<sc->create_labelscnt ; i++) {
671 for (og=0 ; og<MASKORGROUP ; og++) {
672 sc->create_labelmasks[i][og] = master_get32bit();
673 }
674 }
675 for (i=0 ; i<sc->keep_labelscnt ; i++) {
676 for (og=0 ; og<MASKORGROUP ; og++) {
677 sc->keep_labelmasks[i][og] = master_get32bit();
678 }
679 }
680 for (i=0 ; i<sc->arch_labelscnt ; i++) {
681 for (og=0 ; og<MASKORGROUP ; og++) {
682 sc->arch_labelmasks[i][og] = master_get32bit();
683 }
684 }
685 return 0;
686 }
687
serialize_sc(const storage_class * sc)688 static inline void serialize_sc(const storage_class *sc) {
689 uint8_t i,og;
690 master_put8bit(sc->admin_only);
691 master_put8bit(sc->mode);
692 master_put16bit(sc->arch_delay);
693 master_put8bit(sc->create_labelscnt);
694 master_put8bit(sc->keep_labelscnt);
695 master_put8bit(sc->arch_labelscnt);
696 for (i=0 ; i<sc->create_labelscnt ; i++) {
697 for (og=0 ; og<MASKORGROUP ; og++) {
698 master_put32bit(sc->create_labelmasks[i][og]);
699 }
700 }
701 for (i=0 ; i<sc->keep_labelscnt ; i++) {
702 for (og=0 ; og<MASKORGROUP ; og++) {
703 master_put32bit(sc->keep_labelmasks[i][og]);
704 }
705 }
706 for (i=0 ; i<sc->arch_labelscnt ; i++) {
707 for (og=0 ; og<MASKORGROUP ; og++) {
708 master_put32bit(sc->arch_labelmasks[i][og]);
709 }
710 }
711 }
712
printf_sc(const storage_class * sc,char * endstr)713 static inline void printf_sc(const storage_class *sc,char *endstr) {
714 char labelsbuff[LABELS_BUFF_SIZE];
715 if (sc->arch_delay==0) {
716 if (sc->create_labelscnt==sc->keep_labelscnt) {
717 printf("%"PRIu8,sc->create_labelscnt);
718 } else {
719 printf("%"PRIu8"->%"PRIu8,sc->create_labelscnt,sc->keep_labelscnt);
720 }
721 printf(" ; admin_only: %s",(sc->admin_only)?"YES":"NO");
722 printf(" ; mode: %s",(sc->mode==SCLASS_MODE_LOOSE)?"LOOSE":(sc->mode==SCLASS_MODE_STRICT)?"STRICT":"STD");
723 printf(" ; create_labels: %s",make_label_expr(labelsbuff,sc->create_labelscnt,(uint32_t (*)[MASKORGROUP])sc->create_labelmasks));
724 printf(" ; keep_labels: %s",make_label_expr(labelsbuff,sc->keep_labelscnt,(uint32_t (*)[MASKORGROUP])sc->keep_labelmasks));
725 } else {
726 if (sc->create_labelscnt==sc->keep_labelscnt && sc->keep_labelscnt==sc->arch_labelscnt) {
727 printf("%"PRIu8,sc->create_labelscnt);
728 } else {
729 printf("%"PRIu8"->%"PRIu8"->%"PRIu8,sc->create_labelscnt,sc->keep_labelscnt,sc->arch_labelscnt);
730 }
731 printf(" ; admin_only: %s",(sc->admin_only)?"YES":"NO");
732 printf(" ; mode: %s",(sc->mode==SCLASS_MODE_LOOSE)?"LOOSE":(sc->mode==SCLASS_MODE_STRICT)?"STRICT":"STD");
733 printf(" ; create_labels: %s",make_label_expr(labelsbuff,sc->create_labelscnt,(uint32_t (*)[MASKORGROUP])sc->create_labelmasks));
734 printf(" ; keep_labels: %s",make_label_expr(labelsbuff,sc->keep_labelscnt,(uint32_t (*)[MASKORGROUP])sc->keep_labelmasks));
735 printf(" ; arch_labels: %s",make_label_expr(labelsbuff,sc->arch_labelscnt,(uint32_t (*)[MASKORGROUP])sc->arch_labelmasks));
736 printf(" ; arch_delay: %"PRIu16"d",sc->arch_delay);
737 }
738 printf("%s",endstr);
739 }
740
get_sclass(const char * fname,uint8_t * goal,char storage_class_name[256],uint8_t mode)741 int get_sclass(const char *fname,uint8_t *goal,char storage_class_name[256],uint8_t mode) {
742 uint32_t inode;
743 uint8_t fn,dn,i;
744 uint32_t cnt;
745
746 if (master_prepare_conn(fname,&inode,NULL,NULL,0,0)<0) {
747 return -1;
748 }
749 master_new_packet();
750 master_put32bit(inode);
751 master_put8bit(mode);
752 if (master_send_and_receive(CLTOMA_FUSE_GETSCLASS,MATOCL_FUSE_GETSCLASS)<0) {
753 return -1;
754 }
755 if (master_get_leng()==1) {
756 printf("%s: %s\n",fname,mfsstrerr(master_get8bit()));
757 return -1;
758 } else if (master_get_leng()<2) {
759 printf("%s: master query: wrong answer (leng)\n",fname);
760 master_error();
761 return -1;
762 }
763 if (mode==GMODE_NORMAL) {
764 fn = master_get8bit();
765 dn = master_get8bit();
766 if ((fn!=0 || dn!=1) && (fn!=1 || dn!=0)) {
767 printf("%s: master query: wrong answer (fn,dn)\n",fname);
768 master_error();
769 return -1;
770 }
771 *goal = master_get8bit();
772 if (*goal==0) {
773 printf("%s: unsupported data format (upgrade master)\n",fname);
774 return -1;
775 } else if (*goal==0xFF) {
776 master_getname(storage_class_name);
777 }
778 cnt = master_get32bit();
779 if (cnt!=1) {
780 printf("%s: master query: wrong answer (cnt)\n",fname);
781 master_error();
782 return -1;
783 }
784 if (*goal==0xFF) {
785 printf("%s: '%s'\n",fname,storage_class_name);
786 } else {
787 printf("%s: %"PRIu8"\n",fname,*goal);
788 }
789 } else {
790 fn = master_get8bit();
791 dn = master_get8bit();
792 printf("%s:\n",fname);
793 for (i=0 ; i<fn ; i++) {
794 *goal = master_get8bit();
795 if (*goal==0) {
796 printf("%s: unsupported data format (upgrade master)\n",fname);
797 return -1;
798 } else if (*goal==0xFF) {
799 master_getname(storage_class_name);
800 }
801 cnt = master_get32bit();
802 if (*goal==0xFF) {
803 printf(" files with storage class '%s' :",storage_class_name);
804 } else {
805 printf(" files with goal %"PRIu8" :",*goal);
806 }
807 print_number(" ","\n",cnt,1,0,1);
808 }
809 for (i=0 ; i<dn ; i++) {
810 *goal = master_get8bit();
811 if (*goal==0) {
812 printf("%s: unsupported data format (upgrade master)\n",fname);
813 return -1;
814 } else if (*goal==0xFF) {
815 master_getname(storage_class_name);
816 }
817 cnt = master_get32bit();
818 if (*goal==0xFF) {
819 printf(" directories with storage class '%s' :",storage_class_name);
820 } else {
821 printf(" directories with goal %"PRIu8" :",*goal);
822 }
823 print_number(" ","\n",cnt,1,0,1);
824 }
825 }
826 if (master_end_packet()==0) {
827 printf("%s: master query: packet size error\n",fname);
828 return -1;
829 }
830 return 0;
831 }
832
get_trashtime(const char * fname,uint32_t * trashtime,uint8_t mode)833 int get_trashtime(const char *fname,uint32_t *trashtime,uint8_t mode) {
834 uint32_t inode;
835 uint32_t fn,dn,i;
836 // uint32_t trashtime;
837 uint32_t cnt;
838
839 if (master_prepare_conn(fname,&inode,NULL,NULL,0,0)<0) {
840 return -1;
841 }
842 master_new_packet();
843 master_put32bit(inode);
844 master_put8bit(mode);
845 if (master_send_and_receive(CLTOMA_FUSE_GETTRASHTIME,MATOCL_FUSE_GETTRASHTIME)<0) {
846 return -1;
847 }
848 if (master_get_leng()==1) {
849 printf("%s: %s\n",fname,mfsstrerr(master_get8bit()));
850 return -1;
851 } else if (master_get_leng()<8 || master_get_leng()%8!=0) {
852 printf("%s: master query: wrong answer (leng)\n",fname);
853 master_error();
854 return -1;
855 } else if (mode==GMODE_NORMAL && master_get_leng()!=16) {
856 printf("%s: master query: wrong answer (leng)\n",fname);
857 master_error();
858 return -1;
859 }
860 if (mode==GMODE_NORMAL) {
861 fn = master_get32bit();
862 dn = master_get32bit();
863 *trashtime = master_get32bit();
864 cnt = master_get32bit();
865 if ((fn!=0 || dn!=1) && (fn!=1 || dn!=0)) {
866 printf("%s: master query: wrong answer (fn,dn)\n",fname);
867 master_error();
868 return -1;
869 }
870 if (cnt!=1) {
871 printf("%s: master query: wrong answer (cnt)\n",fname);
872 master_error();
873 return -1;
874 }
875 printf("%s: %"PRIu32"\n",fname,*trashtime);
876 } else {
877 fn = master_get32bit();
878 dn = master_get32bit();
879 printf("%s:\n",fname);
880 for (i=0 ; i<fn ; i++) {
881 *trashtime = master_get32bit();
882 cnt = master_get32bit();
883 printf(" files with trashtime %10"PRIu32" :",*trashtime);
884 print_number(" ","\n",cnt,1,0,1);
885 }
886 for (i=0 ; i<dn ; i++) {
887 *trashtime = master_get32bit();
888 cnt = master_get32bit();
889 printf(" directories with trashtime %10"PRIu32" :",*trashtime);
890 print_number(" ","\n",cnt,1,0,1);
891 }
892 }
893 if (master_end_packet()==0) {
894 printf("%s: master query: packet size error\n",fname);
895 return -1;
896 }
897 return 0;
898 }
899
get_eattr(const char * fname,uint8_t * eattr,uint8_t mode)900 int get_eattr(const char *fname,uint8_t *eattr,uint8_t mode) {
901 uint32_t inode;
902 uint8_t fn,dn,i,j;
903 uint32_t fcnt[EATTR_BITS];
904 uint32_t dcnt[EATTR_BITS];
905 // uint8_t eattr;
906 uint32_t cnt;
907
908 if (master_prepare_conn(fname,&inode,NULL,NULL,0,0)<0) {
909 return -1;
910 }
911 master_new_packet();
912 master_put32bit(inode);
913 master_put8bit(mode);
914 if (master_send_and_receive(CLTOMA_FUSE_GETEATTR,MATOCL_FUSE_GETEATTR)<0) {
915 return -1;
916 }
917 if (master_get_leng()==1) {
918 printf("%s: %s\n",fname,mfsstrerr(master_get8bit()));
919 return -1;
920 } else if (master_get_leng()%5!=2) {
921 printf("%s: master query: wrong answer (leng)\n",fname);
922 master_error();
923 return -1;
924 } else if (mode==GMODE_NORMAL && master_get_leng()!=7) {
925 printf("%s: master query: wrong answer (leng)\n",fname);
926 master_error();
927 return -1;
928 }
929 if (mode==GMODE_NORMAL) {
930 fn = master_get8bit();
931 dn = master_get8bit();
932 *eattr = master_get8bit();
933 cnt = master_get32bit();
934 if ((fn!=0 || dn!=1) && (fn!=1 || dn!=0)) {
935 printf("%s: master query: wrong answer (fn,dn)\n",fname);
936 master_error();
937 return -1;
938 }
939 if (cnt!=1) {
940 printf("%s: master query: wrong answer (cnt)\n",fname);
941 master_error();
942 return -1;
943 }
944 printf("%s: ",fname);
945 if (*eattr>0) {
946 cnt=0;
947 for (j=0 ; j<EATTR_BITS ; j++) {
948 if ((*eattr) & (1<<j)) {
949 printf("%s%s",(cnt)?",":"",eattrtab[j]);
950 cnt=1;
951 }
952 }
953 printf("\n");
954 } else {
955 printf("-\n");
956 }
957 } else {
958 for (j=0 ; j<EATTR_BITS ; j++) {
959 fcnt[j]=0;
960 dcnt[j]=0;
961 }
962 fn = master_get8bit();
963 dn = master_get8bit();
964 for (i=0 ; i<fn ; i++) {
965 *eattr = master_get8bit();
966 cnt = master_get32bit();
967 for (j=0 ; j<EATTR_BITS ; j++) {
968 if ((*eattr) & (1<<j)) {
969 fcnt[j]+=cnt;
970 }
971 }
972 }
973 for (i=0 ; i<dn ; i++) {
974 *eattr = master_get8bit();
975 cnt = master_get32bit();
976 for (j=0 ; j<EATTR_BITS ; j++) {
977 if ((*eattr) & (1<<j)) {
978 dcnt[j]+=cnt;
979 }
980 }
981 }
982 printf("%s:\n",fname);
983 for (j=0 ; j<EATTR_BITS ; j++) {
984 if (eattrtab[j][0]) {
985 printf(" not directory nodes with attribute %16s :",eattrtab[j]);
986 print_number(" ","\n",fcnt[j],1,0,1);
987 printf(" directories with attribute %16s :",eattrtab[j]);
988 print_number(" ","\n",dcnt[j],1,0,1);
989 } else {
990 if (fcnt[j]>0) {
991 printf(" not directory nodes with attribute 'unknown-%u' :",j);
992 print_number(" ","\n",fcnt[j],1,0,1);
993 }
994 if (dcnt[j]>0) {
995 printf(" directories with attribute 'unknown-%u' :",j);
996 print_number(" ","\n",dcnt[j],1,0,1);
997 }
998 }
999 }
1000 }
1001 if (master_end_packet()==0) {
1002 printf("%s: master query: packet size error\n",fname);
1003 return -1;
1004 }
1005 return 0;
1006 }
1007
set_sclass(const char * fname,uint8_t goal,const char src_storage_class_name[256],const char storage_class_name[256],uint8_t mode)1008 int set_sclass(const char *fname,uint8_t goal,const char src_storage_class_name[256],const char storage_class_name[256],uint8_t mode) {
1009 uint8_t nleng,snleng;
1010 uint32_t inode,uid;
1011 uint32_t changed,notchanged,notpermitted,quotaexceeded;
1012
1013 nleng = strlen(storage_class_name);
1014 if ((mode&SMODE_TMASK)==SMODE_EXCHANGE) {
1015 snleng = strlen(src_storage_class_name);
1016 } else {
1017 snleng = 0;
1018 }
1019 if (master_prepare_conn(fname,&inode,NULL,NULL,0,1)<0) {
1020 return -1;
1021 }
1022 if (goal==0xFF && master_get_version()<VERSION2INT(3,0,75)) {
1023 printf("%s: storage classes not supported (master too old)\n",fname);
1024 return -1;
1025 }
1026 if (goal==0 || (goal>9 && goal!=0xFF)) {
1027 printf("%s: set storage class unsupported mode (internal error)\n",fname);
1028 return -1;
1029 }
1030 uid = getuid();
1031 master_new_packet();
1032 master_put32bit(inode);
1033 master_put32bit(uid);
1034 master_put8bit(goal);
1035 master_put8bit(mode);
1036 if (goal==0xFF) {
1037 if ((mode&SMODE_TMASK)==SMODE_EXCHANGE) {
1038 master_putname(snleng,src_storage_class_name);
1039 }
1040 master_putname(nleng,storage_class_name);
1041 }
1042 if (master_send_and_receive(CLTOMA_FUSE_SETSCLASS,MATOCL_FUSE_SETSCLASS)<0) {
1043 return -1;
1044 }
1045 if (master_get_leng()==1) {
1046 printf("%s: %s\n",fname,mfsstrerr(master_get8bit()));
1047 return -1;
1048 } else if (master_get_leng()!=12 && master_get_leng()!=16) {
1049 printf("%s: master query: wrong answer (leng)\n",fname);
1050 master_error();
1051 return -1;
1052 }
1053 changed = master_get32bit();
1054 notchanged = master_get32bit();
1055 notpermitted = master_get32bit();
1056 if (master_get_leng()==16) {
1057 quotaexceeded = master_get32bit();
1058 } else {
1059 quotaexceeded = 0;
1060 }
1061 if ((mode&SMODE_RMASK)==0) {
1062 if (changed || mode==SMODE_SET) {
1063 if (goal==0xFF) {
1064 printf("%s: storage class: '%s'\n",fname,storage_class_name);
1065 } else {
1066 printf("%s: goal: %"PRIu8"\n",fname,goal);
1067 }
1068 } else {
1069 if (goal==0xFF) {
1070 printf("%s: storage class not changed\n",fname);
1071 } else {
1072 printf("%s: goal not changed\n",fname);
1073 }
1074 }
1075 } else {
1076 printf("%s:\n",fname);
1077 if (goal==0xFF) {
1078 print_number(" inodes with storage class changed: ","\n",changed,1,0,1);
1079 print_number(" inodes with storage class not changed: ","\n",notchanged,1,0,1);
1080 } else {
1081 print_number(" inodes with goal changed: ","\n",changed,1,0,1);
1082 print_number(" inodes with goal not changed: ","\n",notchanged,1,0,1);
1083 }
1084 print_number(" inodes with permission denied: ","\n",notpermitted,1,0,1);
1085 if (master_get_leng()==16) {
1086 print_number(" inodes with quota exceeded: ","\n",quotaexceeded,1,0,1);
1087 }
1088 }
1089 if (master_end_packet()==0) {
1090 printf("%s: master query: packet size error\n",fname);
1091 return -1;
1092 }
1093 return 0;
1094 }
1095
set_trashtime(const char * fname,uint32_t trashtime,uint8_t mode)1096 int set_trashtime(const char *fname,uint32_t trashtime,uint8_t mode) {
1097 uint32_t inode,uid;
1098 uint32_t changed,notchanged,notpermitted;
1099
1100 if (master_prepare_conn(fname,&inode,NULL,NULL,0,1)<0) {
1101 return -1;
1102 }
1103 uid = getuid();
1104 master_new_packet();
1105 master_put32bit(inode);
1106 master_put32bit(uid);
1107 master_put32bit(trashtime);
1108 master_put8bit(mode);
1109 if (master_send_and_receive(CLTOMA_FUSE_SETTRASHTIME,MATOCL_FUSE_SETTRASHTIME)<0) {
1110 return -1;
1111 }
1112 if (master_get_leng()==1) {
1113 printf("%s: %s\n",fname,mfsstrerr(master_get8bit()));
1114 return -1;
1115 } else if (master_get_leng()!=12) {
1116 printf("%s: master query: wrong answer (leng)\n",fname);
1117 master_error();
1118 return -1;
1119 }
1120 changed = master_get32bit();
1121 notchanged = master_get32bit();
1122 notpermitted = master_get32bit();
1123 if ((mode&SMODE_RMASK)==0) {
1124 if (changed || mode==SMODE_SET) {
1125 printf("%s: %"PRIu32"\n",fname,trashtime);
1126 } else {
1127 printf("%s: trashtime not changed\n",fname);
1128 }
1129 } else {
1130 printf("%s:\n",fname);
1131 print_number(" inodes with trashtime changed: ","\n",changed,1,0,1);
1132 print_number(" inodes with trashtime not changed: ","\n",notchanged,1,0,1);
1133 print_number(" inodes with permission denied: ","\n",notpermitted,1,0,1);
1134 }
1135 if (master_end_packet()==0) {
1136 printf("%s: master query: packet size error\n",fname);
1137 return -1;
1138 }
1139 return 0;
1140 }
1141
set_eattr(const char * fname,uint8_t eattr,uint8_t mode)1142 int set_eattr(const char *fname,uint8_t eattr,uint8_t mode) {
1143 uint32_t inode,uid;
1144 uint32_t changed,notchanged,notpermitted;
1145
1146 if (master_prepare_conn(fname,&inode,NULL,NULL,0,1)<0) {
1147 return -1;
1148 }
1149 uid = getuid();
1150 master_new_packet();
1151 master_put32bit(inode);
1152 master_put32bit(uid);
1153 master_put8bit(eattr);
1154 master_put8bit(mode);
1155 if (master_send_and_receive(CLTOMA_FUSE_SETEATTR,MATOCL_FUSE_SETEATTR)<0) {
1156 return -1;
1157 }
1158 if (master_get_leng()==1) {
1159 printf("%s: %s\n",fname,mfsstrerr(master_get8bit()));
1160 return -1;
1161 } else if (master_get_leng()!=12) {
1162 printf("%s: master query: wrong answer (leng)\n",fname);
1163 master_error();
1164 return -1;
1165 }
1166 changed = master_get32bit();
1167 notchanged = master_get32bit();
1168 notpermitted = master_get32bit();
1169 if ((mode&SMODE_RMASK)==0) {
1170 if (changed) {
1171 printf("%s: attribute(s) changed\n",fname);
1172 } else {
1173 printf("%s: attribute(s) not changed\n",fname);
1174 }
1175 } else {
1176 printf("%s:\n",fname);
1177 print_number(" inodes with attributes changed: ","\n",changed,1,0,1);
1178 print_number(" inodes with attributes not changed: ","\n",notchanged,1,0,1);
1179 print_number(" inodes with permission denied: ","\n",notpermitted,1,0,1);
1180 }
1181 if (master_end_packet()==0) {
1182 printf("%s: master query: packet size error\n",fname);
1183 return -1;
1184 }
1185 return 0;
1186 }
1187
archive_control(const char * fname,uint8_t archcmd)1188 int archive_control(const char *fname,uint8_t archcmd) {
1189 uint32_t inode,uid;
1190
1191 if (master_prepare_conn(fname,&inode,NULL,NULL,0,1)<0) {
1192 return -1;
1193 }
1194 uid = getuid();
1195 master_new_packet();
1196 master_put32bit(inode);
1197 master_put8bit(archcmd);
1198 if (archcmd!=ARCHCTL_GET) {
1199 master_put32bit(uid);
1200 }
1201 if (master_send_and_receive(CLTOMA_FUSE_ARCHCTL,MATOCL_FUSE_ARCHCTL)<0) {
1202 return -1;
1203 }
1204 if (master_get_leng()==1) {
1205 printf("%s: %s\n",fname,mfsstrerr(master_get8bit()));
1206 return -1;
1207 }
1208 if (archcmd==ARCHCTL_GET) {
1209 uint32_t archinodes,partinodes,notarchinodes;
1210 uint64_t archchunks,notarchchunks;
1211 if (master_get_leng()!=28) {
1212 printf("%s: master query: wrong answer (leng)\n",fname);
1213 master_error();
1214 return -1;
1215 }
1216 archchunks = master_get64bit();
1217 notarchchunks = master_get64bit();
1218 archinodes = master_get32bit();
1219 partinodes = master_get32bit();
1220 notarchinodes = master_get32bit();
1221 if (archinodes+partinodes+notarchinodes==1) {
1222 if (archinodes==1) {
1223 printf("%s: all chunks are archived\n",fname);
1224 } else if (notarchinodes==1) {
1225 printf("%s: all chunks are not archived\n",fname);
1226 } else {
1227 printf("%s: file is partially archived (archived chunks: %"PRIu64" ; not archived chunks: %"PRIu64")\n",fname,archchunks,notarchchunks);
1228 }
1229 } else {
1230 printf("%s:\n",fname);
1231 print_number(" files with all chunks archived: ","\n",archinodes,1,0,1);
1232 print_number(" files with all chunks not archived: ","\n",notarchinodes,1,0,1);
1233 print_number(" files partially archived: ","\n",partinodes,1,0,1);
1234 print_number(" archived chunks: ","\n",archchunks,1,0,1);
1235 print_number(" not archived chunks: ","\n",notarchchunks,1,0,1);
1236 }
1237 } else {
1238 uint64_t changed,notchanged;
1239 uint32_t notpermitted;
1240 if (master_get_leng()!=20) {
1241 printf("%s: master query: wrong answer (leng)\n",fname);
1242 master_error();
1243 return -1;
1244 }
1245 changed = master_get64bit();
1246 notchanged = master_get64bit();
1247 notpermitted = master_get32bit();
1248 printf("%s:\n",fname);
1249 print_number(" chunks changed: ","\n",changed,1,0,1);
1250 print_number(" chunks not changed: ","\n",notchanged,1,0,1);
1251 print_number(" files with permission denied: ","\n",notpermitted,1,0,1);
1252 }
1253 if (master_end_packet()==0) {
1254 printf("%s: master query: packet size error\n",fname);
1255 return -1;
1256 }
1257 return 0;
1258 }
1259
make_sc(const char * mfsmp,const char * scname,storage_class * sc)1260 int make_sc(const char *mfsmp,const char *scname,storage_class *sc) {
1261 uint32_t nleng;
1262 char cwdbuff[MAXPATHLEN];
1263 uint8_t status;
1264
1265 nleng = strlen(scname);
1266 if (nleng>=256) {
1267 printf("%s: name too long\n",scname);
1268 return -1;
1269 }
1270 if (mfsmp==NULL) {
1271 mfsmp = getcwd(cwdbuff,MAXPATHLEN);
1272 }
1273 if (master_prepare_conn(mfsmp,NULL,NULL,NULL,0,0)<0) {
1274 return -1;
1275 }
1276 master_new_packet();
1277 master_putname(nleng,scname);
1278 master_put8bit(0); // packet version
1279 serialize_sc(sc);
1280 if (master_send_and_receive(CLTOMA_SCLASS_CREATE,MATOCL_SCLASS_CREATE)<0) {
1281 return -1;
1282 }
1283 if (master_get_leng()!=1) {
1284 printf("master query: wrong answer (leng)\n");
1285 master_error();
1286 return -1;
1287 }
1288 status = master_get8bit();
1289 if (status!=MFS_STATUS_OK) {
1290 printf("storage class make %s: error: %s\n",scname,mfsstrerr(status));
1291 return -1;
1292 }
1293 printf("storage class make %s: ok\n",scname);
1294 if (master_end_packet()==0) { // pro forma
1295 printf("master query: packet size error\n");
1296 return -1;
1297 }
1298 return 0;
1299 }
1300
change_sc(const char * mfsmp,const char * scname,uint16_t chgmask,storage_class * sc)1301 int change_sc(const char *mfsmp,const char *scname,uint16_t chgmask,storage_class *sc) {
1302 uint32_t nleng;
1303 char cwdbuff[MAXPATHLEN];
1304
1305 nleng = strlen(scname);
1306 if (nleng>=256) {
1307 printf("%s: name too long\n",scname);
1308 return -1;
1309 }
1310 if (mfsmp==NULL) {
1311 mfsmp = getcwd(cwdbuff,MAXPATHLEN);
1312 }
1313 if (master_prepare_conn(mfsmp,NULL,NULL,NULL,0,0)<0) {
1314 return -1;
1315 }
1316 master_new_packet();
1317 master_putname(nleng,scname);
1318 master_put8bit(0); // packet version
1319 master_put16bit(chgmask);
1320 serialize_sc(sc);
1321 if (master_send_and_receive(CLTOMA_SCLASS_CHANGE,MATOCL_SCLASS_CHANGE)<0) {
1322 return -1;
1323 }
1324 if (master_get_leng()==0) {
1325 printf("master query: wrong answer (leng)\n");
1326 master_error();
1327 return -1;
1328 }
1329 if (master_get_leng()==1) {
1330 if (chgmask==0) {
1331 printf("storage class show %s: error: %s\n",scname,mfsstrerr(master_get8bit()));
1332 } else {
1333 printf("storage class change %s: error: %s\n",scname,mfsstrerr(master_get8bit()));
1334 }
1335 return -1;
1336 }
1337 if (master_get8bit()!=0) {
1338 printf("master query: wrong answer (wrong data format)\n");
1339 master_error();
1340 return -1;
1341 }
1342 if (deserialize_sc(sc)<0) {
1343 printf("master query: wrong answer (deserialize storage class)\n");
1344 master_error();
1345 return -1;
1346 }
1347 printf("storage class change %s: ",scname);
1348 printf_sc(sc,"\n");
1349 if (master_end_packet()==0) {
1350 printf("master query: packet size error\n");
1351 return -1;
1352 }
1353 return 0;
1354 }
1355
show_sc(const char * mfsmp,const char * scname)1356 int show_sc(const char *mfsmp,const char *scname) {
1357 storage_class sc;
1358 memset(&sc,0,sizeof(storage_class));
1359 return change_sc(mfsmp,scname,0,&sc);
1360 }
1361
remove_sc(const char * mfsmp,const char * scname)1362 int remove_sc(const char *mfsmp,const char *scname) {
1363 uint32_t nleng;
1364 char cwdbuff[MAXPATHLEN];
1365 uint8_t status;
1366
1367 nleng = strlen(scname);
1368 if (nleng>=256) {
1369 printf("%s: name too long\n",scname);
1370 return -1;
1371 }
1372 if (mfsmp==NULL) {
1373 mfsmp = getcwd(cwdbuff,MAXPATHLEN);
1374 }
1375 if (master_prepare_conn(mfsmp,NULL,NULL,NULL,0,0)<0) {
1376 return -1;
1377 }
1378 master_new_packet();
1379 master_putname(nleng,scname);
1380 if (master_send_and_receive(CLTOMA_SCLASS_DELETE,MATOCL_SCLASS_DELETE)<0) {
1381 return -1;
1382 }
1383 if (master_get_leng()!=1) {
1384 printf("master query: wrong answer (leng)\n");
1385 master_error();
1386 return -1;
1387 }
1388 status = master_get8bit();
1389 if (status!=MFS_STATUS_OK) {
1390 printf("storage class remove %s: error: %s\n",scname,mfsstrerr(status));
1391 return -1;
1392 }
1393 printf("storage class remove %s: ok\n",scname);
1394 if (master_end_packet()==0) { // pro forma
1395 printf("master query: packet size error\n");
1396 return -1;
1397 }
1398 return 0;
1399 }
1400
copy_sc(const char * mfsmp,const char * oldscname,const char * newscname)1401 int copy_sc(const char *mfsmp,const char *oldscname,const char *newscname) {
1402 uint32_t onleng,nnleng;
1403 char cwdbuff[MAXPATHLEN];
1404 uint8_t status;
1405
1406 onleng = strlen(oldscname);
1407 nnleng = strlen(newscname);
1408 if (onleng>=256) {
1409 printf("%s: name too long\n",oldscname);
1410 return -1;
1411 }
1412 if (nnleng>=256) {
1413 printf("%s: name too long\n",newscname);
1414 return -1;
1415 }
1416 if (mfsmp==NULL) {
1417 mfsmp = getcwd(cwdbuff,MAXPATHLEN);
1418 }
1419 if (master_prepare_conn(mfsmp,NULL,NULL,NULL,0,0)<0) {
1420 return -1;
1421 }
1422
1423 master_new_packet();
1424 master_putname(onleng,oldscname);
1425 master_putname(nnleng,newscname);
1426 if (master_send_and_receive(CLTOMA_SCLASS_DUPLICATE,MATOCL_SCLASS_DUPLICATE)<0) {
1427 return -1;
1428 }
1429 if (master_get_leng()!=1) {
1430 printf("master query: wrong answer (leng)\n");
1431 master_error();
1432 return -1;
1433 }
1434 status = master_get8bit();
1435 if (status!=MFS_STATUS_OK) {
1436 printf("storage class copy %s->%s: error: %s\n",oldscname,newscname,mfsstrerr(status));
1437 return -1;
1438 }
1439 printf("storage class copy %s->%s: ok\n",oldscname,newscname);
1440 if (master_end_packet()==0) { // pro forma
1441 printf("master query: packet size error\n");
1442 return -1;
1443 }
1444 return 0;
1445 }
1446
move_sc(const char * mfsmp,const char * oldscname,const char * newscname)1447 int move_sc(const char *mfsmp,const char *oldscname,const char *newscname) {
1448 uint32_t onleng,nnleng;
1449 char cwdbuff[MAXPATHLEN];
1450 uint8_t status;
1451
1452 onleng = strlen(oldscname);
1453 nnleng = strlen(newscname);
1454 if (onleng>=256) {
1455 printf("%s: name too long\n",oldscname);
1456 return -1;
1457 }
1458 if (nnleng>=256) {
1459 printf("%s: name too long\n",newscname);
1460 return -1;
1461 }
1462 if (mfsmp==NULL) {
1463 mfsmp = getcwd(cwdbuff,MAXPATHLEN);
1464 }
1465 if (master_prepare_conn(mfsmp,NULL,NULL,NULL,0,0)<0) {
1466 return -1;
1467 }
1468
1469 master_new_packet();
1470 master_putname(onleng,oldscname);
1471 master_putname(nnleng,newscname);
1472 if (master_send_and_receive(CLTOMA_SCLASS_RENAME,MATOCL_SCLASS_RENAME)<0) {
1473 return -1;
1474 }
1475 if (master_get_leng()!=1) {
1476 printf("master query: wrong answer (leng)\n");
1477 master_error();
1478 return -1;
1479 }
1480 status = master_get8bit();
1481 if (status!=MFS_STATUS_OK) {
1482 printf("storage class move %s->%s: error: %s\n",oldscname,newscname,mfsstrerr(status));
1483 return -1;
1484 }
1485 printf("storage class move %s->%s: ok\n",oldscname,newscname);
1486 if (master_end_packet()==0) { // pro forma
1487 printf("master query: packet size error\n");
1488 return -1;
1489 }
1490 return 0;
1491 }
1492
list_sc(const char * mfsmp,uint8_t longmode)1493 int list_sc(const char *mfsmp,uint8_t longmode) {
1494 char scname[256];
1495 storage_class sc;
1496 char cwdbuff[MAXPATHLEN];
1497
1498 if (mfsmp==NULL) {
1499 mfsmp = getcwd(cwdbuff,MAXPATHLEN);
1500 }
1501 if (master_prepare_conn(mfsmp,NULL,NULL,NULL,0,0)<0) {
1502 return -1;
1503 }
1504
1505 master_new_packet();
1506 master_put8bit(longmode);
1507 if (master_send_and_receive(CLTOMA_SCLASS_LIST,MATOCL_SCLASS_LIST)<0) {
1508 return -1;
1509 }
1510 if (master_get_leng()==1) {
1511 printf("storage class list: error: %s\n",mfsstrerr(master_get8bit()));
1512 return -1;
1513 }
1514 while (master_bytes_left()>0) {
1515 master_getname(scname);
1516 if (longmode&1) {
1517 if (deserialize_sc(&sc)<0) {
1518 printf("master query: wrong answer (deserialize storage class)\n");
1519 master_error();
1520 return -1;
1521 }
1522 printf("%s : ",scname);
1523 printf_sc(&sc,"\n");
1524 } else {
1525 printf("%s\n",scname);
1526 }
1527 }
1528 if (master_end_packet()==0) {
1529 printf("master query: packet size error\n");
1530 return -1;
1531 }
1532 return 0;
1533 }
1534
1535 typedef struct _chunk_data {
1536 uint32_t ip;
1537 uint16_t port;
1538 uint8_t status;
1539 } chunk_data;
1540
chunk_data_cmp(const void * a,const void * b)1541 int chunk_data_cmp(const void*a,const void*b) {
1542 chunk_data *aa = (chunk_data*)a;
1543 chunk_data *bb = (chunk_data*)b;
1544
1545 if (aa->ip < bb->ip) {
1546 return -1;
1547 } else if (aa->ip > bb->ip) {
1548 return 1;
1549 } else if (aa->port < bb->port) {
1550 return -1;
1551 } else if (aa->port > bb->port) {
1552 return 1;
1553 }
1554 return 0;
1555 }
1556
get_checksum_block(const char * csstrip,uint32_t csip,uint16_t csport,uint64_t chunkid,uint32_t version,uint8_t crcblock[4096],uint16_t * blocks)1557 int get_checksum_block(const char *csstrip,uint32_t csip,uint16_t csport,uint64_t chunkid,uint32_t version,uint8_t crcblock[4096],uint16_t *blocks) {
1558 uint8_t reqbuff[20],*wptr,*buff;
1559 const uint8_t *rptr;
1560 int fd;
1561 uint32_t cmd,leng;
1562 uint16_t cnt;
1563 uint8_t status;
1564
1565 buff = NULL;
1566 fd = -1;
1567 cnt=0;
1568 while (cnt<10) {
1569 fd = tcpsocket();
1570 if (fd<0) {
1571 printf("can't create connection socket: %s\n",strerr(errno));
1572 goto error;
1573 }
1574 if (tcpnumtoconnect(fd,csip,csport,(cnt%2)?(300*(1<<(cnt>>1))):(200*(1<<(cnt>>1))))<0) {
1575 cnt++;
1576 if (cnt==10) {
1577 printf("can't connect to chunkserver %s:%"PRIu16": %s\n",csstrip,csport,strerr(errno));
1578 goto error;
1579 }
1580 tcpclose(fd);
1581 fd = -1;
1582 } else {
1583 cnt=10;
1584 }
1585 }
1586
1587 // 1 - get checksum block
1588 buff = NULL;
1589 wptr = reqbuff;
1590 put32bit(&wptr,ANTOCS_GET_CHUNK_CHECKSUM_TAB);
1591 put32bit(&wptr,12);
1592 put64bit(&wptr,chunkid);
1593 put32bit(&wptr,version);
1594 if (tcpwrite(fd,reqbuff,20)!=20) {
1595 printf("%s:%"PRIu16": cs query: send error\n",csstrip,csport);
1596 goto error;
1597 }
1598 if (tcpread(fd,reqbuff,8)!=8) {
1599 printf("%s:%"PRIu16" cs query: receive error\n",csstrip,csport);
1600 goto error;
1601 }
1602 rptr = reqbuff;
1603 cmd = get32bit(&rptr);
1604 leng = get32bit(&rptr);
1605 if (cmd!=CSTOAN_CHUNK_CHECKSUM_TAB) {
1606 printf("%s:%"PRIu16" cs query: wrong answer (type)\n",csstrip,csport);
1607 goto error;
1608 }
1609 if (leng!=13 && leng!=(4096+12)) {
1610 printf("%s:%"PRIu16" cs query: wrong answer (size)\n",csstrip,csport);
1611 goto error;
1612 }
1613 buff = malloc(leng);
1614 if (tcpread(fd,buff,leng)!=(int32_t)leng) {
1615 printf("%s:%"PRIu16" cs query: receive error\n",csstrip,csport);
1616 goto error;
1617 }
1618 rptr = buff;
1619 if (chunkid!=get64bit(&rptr)) {
1620 printf("%s:%"PRIu16" cs query: wrong answer (chunkid)\n",csstrip,csport);
1621 goto error;
1622 }
1623 if (version!=get32bit(&rptr)) {
1624 printf("%s:%"PRIu16" cs query: wrong answer (version)\n",csstrip,csport);
1625 goto error;
1626 }
1627 leng-=12;
1628 if (leng==1) {
1629 printf("%s:%"PRIu16" cs query error: %s\n",csstrip,csport,mfsstrerr(*rptr));
1630 goto error;
1631 }
1632 memcpy(crcblock,rptr,4096);
1633 free(buff);
1634
1635 // 2 - get number of blocks
1636 buff = NULL;
1637 wptr = reqbuff;
1638 put32bit(&wptr,ANTOCS_GET_CHUNK_BLOCKS);
1639 put32bit(&wptr,12);
1640 put64bit(&wptr,chunkid);
1641 put32bit(&wptr,version);
1642 if (tcpwrite(fd,reqbuff,20)!=20) {
1643 printf("%s:%"PRIu16": cs query: send error\n",csstrip,csport);
1644 goto error;
1645 }
1646 if (tcpread(fd,reqbuff,8)!=8) {
1647 printf("%s:%"PRIu16" cs query: receive error\n",csstrip,csport);
1648 goto error;
1649 }
1650 rptr = reqbuff;
1651 cmd = get32bit(&rptr);
1652 leng = get32bit(&rptr);
1653 if (cmd!=CSTOAN_CHUNK_BLOCKS) {
1654 printf("%s:%"PRIu16" cs query: wrong answer (type)\n",csstrip,csport);
1655 goto error;
1656 }
1657 if (leng!=15) {
1658 printf("%s:%"PRIu16" cs query: wrong answer (size)\n",csstrip,csport);
1659 goto error;
1660 }
1661 buff = malloc(leng);
1662 if (tcpread(fd,buff,leng)!=(int32_t)leng) {
1663 printf("%s:%"PRIu16" cs query: receive error\n",csstrip,csport);
1664 goto error;
1665 }
1666 rptr = buff;
1667 if (chunkid!=get64bit(&rptr)) {
1668 printf("%s:%"PRIu16" cs query: wrong answer (chunkid)\n",csstrip,csport);
1669 goto error;
1670 }
1671 if (version!=get32bit(&rptr)) {
1672 printf("%s:%"PRIu16" cs query: wrong answer (version)\n",csstrip,csport);
1673 goto error;
1674 }
1675 *blocks = get16bit(&rptr);
1676 status = get8bit(&rptr);
1677 if (status!=MFS_STATUS_OK) {
1678 printf("%s:%"PRIu16" cs query error: %s\n",csstrip,csport,mfsstrerr(status));
1679 goto error;
1680 }
1681 free(buff);
1682
1683 tcpclose(fd);
1684 return 0;
1685
1686 error:
1687 if (buff!=NULL) {
1688 free(buff);
1689 }
1690 if (fd>=0) {
1691 tcpclose(fd);
1692 }
1693 return -1;
1694 }
1695
digest_to_str(char strdigest[33],uint8_t digest[16])1696 void digest_to_str(char strdigest[33],uint8_t digest[16]) {
1697 uint32_t i;
1698 for (i=0 ; i<16 ; i++) {
1699 snprintf(strdigest+2*i,3,"%02X",digest[i]);
1700 }
1701 strdigest[32]='\0';
1702 }
1703
file_info(uint8_t fileinfomode,const char * fname)1704 int file_info(uint8_t fileinfomode,const char *fname) {
1705 uint32_t fchunks;
1706 uint8_t fchunksvalid;
1707 uint32_t indx,inode,version;
1708 uint32_t chunks,copies,vcopies,copy;
1709 char *strtype;
1710 char csstrip[16];
1711 chunk_data *cdtab;
1712 uint8_t protover;
1713 uint64_t chunkid;
1714 uint64_t fleng;
1715 uint8_t crcblock[4096];
1716 uint16_t blocks;
1717 md5ctx filectx,chunkctx;
1718 uint8_t chunkdigest[16],currentdigest[16];
1719 uint8_t firstdigest;
1720 uint8_t checksumerror;
1721 char strdigest[33];
1722
1723 if (master_prepare_conn(fname,&inode,NULL,&fleng,0,0)<0) {
1724 return -1;
1725 }
1726 master_new_packet();
1727 master_put32bit(inode);
1728 if (master_send_and_receive(CLTOMA_FUSE_CHECK,MATOCL_FUSE_CHECK)<0) {
1729 return -1;
1730 }
1731 if (master_get_leng()==1) {
1732 printf("%s: %s\n",fname,mfsstrerr(master_get8bit()));
1733 return -1;
1734 } else if ((master_get_leng()%3!=0 || master_get_leng()>33) && master_get_leng()!=44 && master_get_leng()!=48) {
1735 printf("%s: master query: wrong answer (leng)\n",fname);
1736 master_error();
1737 return -1;
1738 }
1739 if (fileinfomode&FILEINFO_QUICK) {
1740 printf("%s:\n",fname);
1741 }
1742 fchunks = 0;
1743 fchunksvalid = 0;
1744 if (master_get_leng()%3==0 && master_get_leng()<=33) {
1745 while (master_bytes_left()>0) {
1746 copies = master_get8bit();
1747 chunks = master_get16bit();
1748 if (fileinfomode&FILEINFO_QUICK) {
1749 if (copies==1) {
1750 printf("1 copy:");
1751 } else {
1752 printf("%"PRIu32" copies:",copies);
1753 }
1754 print_number(" ","\n",chunks,1,0,1);
1755 }
1756 fchunks += chunks;
1757 }
1758 } else {
1759 for (copies=0 ; copies<11 ; copies++) {
1760 chunks = master_get32bit();
1761 if (chunks>0 && (fileinfomode&FILEINFO_QUICK)) {
1762 if (copies==1) {
1763 printf(" chunks with 1 copy: ");
1764 } else if (copies>=10) {
1765 printf(" chunks with 10+ copies:");
1766 } else {
1767 printf(" chunks with %u copies: ",copies);
1768 }
1769 print_number(" ","\n",chunks,1,0,1);
1770 }
1771 fchunks += chunks;
1772 }
1773 if (master_get_leng()==48) {
1774 chunks = master_get32bit();
1775 if (chunks>0 && (fileinfomode&FILEINFO_QUICK)) {
1776 printf(" empty (zero) chunks: ");
1777 print_number(" ","\n",chunks,1,0,1);
1778 }
1779 fchunks += chunks;
1780 fchunksvalid = 1;
1781 }
1782 }
1783 if (master_end_packet()==0) {
1784 printf("%s: master query: packet size error\n",fname);
1785 return -1;
1786 }
1787 if ((fileinfomode&FILEINFO_QUICK)==0) {
1788 if (fchunksvalid==0) { // in this case fchunks doesn't include 'empty' chunks, so use file size to fix 'fchunks' if necessary
1789 if (fchunks < ((fleng+MFSCHUNKMASK)>>MFSCHUNKBITS)) {
1790 fchunks = ((fleng+MFSCHUNKMASK)>>MFSCHUNKBITS);
1791 }
1792 }
1793 // printf("masterversion: %08X\n",masterversion);
1794 if (fileinfomode&FILEINFO_SIGNATURE) {
1795 md5_init(&filectx);
1796 }
1797 printf("%s:\n",fname);
1798 if (fchunks==0) {
1799 printf("\tno chunks - empty file\n");
1800 }
1801 for (indx=0 ; indx<fchunks ; indx++) {
1802 master_new_packet();
1803 if (master_get_version()<VERSION2INT(3,0,26)) {
1804 uint32_t leng;
1805 master_put32bit(inode);
1806 master_put32bit(indx);
1807 if (master_get_version()>=VERSION2INT(3,0,3)) {
1808 master_put8bit(0); // canmodatime
1809 }
1810 if (master_send_and_receive(CLTOMA_FUSE_READ_CHUNK,MATOCL_FUSE_READ_CHUNK)<0) {
1811 return -1;
1812 }
1813 leng = master_get_leng();
1814 if (leng==1) {
1815 printf("%s [%"PRIu32"]: %s\n",fname,indx,mfsstrerr(master_get8bit()));
1816 return -1;
1817 } else if (leng&1) {
1818 protover = master_get8bit();
1819 if (protover!=1 && protover!=2) {
1820 printf("%s [%"PRIu32"]: master query: unknown protocol id (%"PRIu8")\n",fname,indx,protover);
1821 master_error();
1822 return -1;
1823 }
1824 if (leng<21 || (protover==1 && ((leng-21)%10)!=0) || (protover==2 && ((leng-21)%14)!=0)) {
1825 printf("%s [%"PRIu32"]: master query: wrong answer (leng)\n",fname,indx);
1826 master_error();
1827 return -1;
1828 }
1829 } else {
1830 if (leng<20 || ((leng-20)%6)!=0) {
1831 printf("%s [%"PRIu32"]: master query: wrong answer (leng)\n",fname,indx);
1832 master_error();
1833 return -1;
1834 }
1835 protover = 0;
1836 }
1837 (void)master_get64bit(); // fleng
1838 if (protover==2) {
1839 copies = (leng-21)/14;
1840 } else if (protover==1) {
1841 copies = (leng-21)/10;
1842 } else {
1843 copies = (leng-20)/6;
1844 }
1845 } else {
1846 master_put32bit(inode);
1847 master_put32bit(indx);
1848 if (master_send_and_receive(CLTOMA_FUSE_CHECK,MATOCL_FUSE_CHECK)<0) {
1849 return -1;
1850 }
1851 if (master_get_leng()==1) {
1852 printf("%s [%"PRIu32"]: %s\n",fname,indx,mfsstrerr(master_get8bit()));
1853 return -1;
1854 } else {
1855 if (master_get_leng()<12 || ((master_get_leng()-12)%7)!=0) {
1856 printf("%s [%"PRIu32"]: master query: wrong answer (leng)\n",fname,indx);
1857 master_error();
1858 return -1;
1859 }
1860 protover = 255;
1861 copies = (master_get_leng()-12)/7;
1862 }
1863 }
1864 chunkid = master_get64bit();
1865 version = master_get32bit();
1866 if (chunkid==0 && version==0) {
1867 printf("\tchunk %"PRIu32": empty\n",indx);
1868 } else {
1869 printf("\tchunk %"PRIu32": %016"PRIX64"_%08"PRIX32" / (id:%"PRIu64" ver:%"PRIu32")\n",indx,chunkid,version,chunkid,version);
1870 vcopies = 0;
1871 if (copies>0) {
1872 cdtab = malloc(copies*sizeof(chunk_data));
1873 } else {
1874 cdtab = NULL;
1875 }
1876 for (copy=0 ; copy<copies ; copy++) {
1877 cdtab[copy].ip = master_get32bit();
1878 cdtab[copy].port = master_get16bit();
1879 if (protover==255) {
1880 cdtab[copy].status = master_get8bit();
1881 } else {
1882 cdtab[copy].status = CHECK_VALID;
1883 if (protover>=1) {
1884 (void)master_get32bit();
1885 }
1886 if (protover>=2) {
1887 (void)master_get32bit();
1888 }
1889 }
1890 }
1891 if (copies>0) {
1892 qsort(cdtab,copies,sizeof(chunk_data),chunk_data_cmp);
1893 }
1894 firstdigest = 1;
1895 checksumerror = 0;
1896 for (copy=0 ; copy<copies ; copy++) {
1897 snprintf(csstrip,16,"%"PRIu8".%"PRIu8".%"PRIu8".%"PRIu8,(uint8_t)((cdtab[copy].ip>>24)&0xFF),(uint8_t)((cdtab[copy].ip>>16)&0xFF),(uint8_t)((cdtab[copy].ip>>8)&0xFF),(uint8_t)(cdtab[copy].ip&0xFF));
1898 csstrip[15]=0;
1899 if (protover==255) {
1900 switch (cdtab[copy].status) {
1901 case CHECK_VALID:
1902 strtype = "VALID";
1903 vcopies++;
1904 break;
1905 case CHECK_MARKEDFORREMOVAL:
1906 strtype = "MARKED FOR REMOVAL";
1907 break;
1908 case CHECK_WRONGVERSION:
1909 strtype = "WRONG VERSION";
1910 break;
1911 case CHECK_WV_AND_MFR:
1912 strtype = "WRONG VERSION , MARKED FOR REMOVAL";
1913 break;
1914 case CHECK_INVALID:
1915 strtype = "INVALID";
1916 break;
1917 default:
1918 strtype = "???";
1919 }
1920 } else if (protover==2) {
1921 strtype = "VALID";
1922 vcopies++;
1923 } else if (protover==1) {
1924 strtype = "VALID";
1925 vcopies++;
1926 } else {
1927 strtype = "VALID";
1928 vcopies++;
1929 }
1930 if (fileinfomode&(FILEINFO_CRC|FILEINFO_SIGNATURE)) {
1931 if (get_checksum_block(csstrip,cdtab[copy].ip,cdtab[copy].port,chunkid,version,crcblock,&blocks)==0) {
1932 md5_init(&chunkctx);
1933 md5_update(&chunkctx,crcblock,4*blocks);
1934 if ((fileinfomode&FILEINFO_SIGNATURE) && firstdigest) {
1935 md5_update(&filectx,crcblock,4*blocks);
1936 }
1937 md5_final(currentdigest,&chunkctx);
1938 if (firstdigest) {
1939 memcpy(chunkdigest,currentdigest,16);
1940 } else {
1941 if (memcmp(chunkdigest,currentdigest,16)!=0) {
1942 checksumerror = 1;
1943 }
1944 }
1945 firstdigest = 0;
1946 if (fileinfomode&FILEINFO_CRC) {
1947 digest_to_str(strdigest,currentdigest);
1948 printf("\t\tcopy %"PRIu32": %s:%"PRIu16" (status:%s ; blocks: %u ; checksum digest: %s)\n",copy+1,csstrip,cdtab[copy].port,strtype,blocks,strdigest);
1949 } else {
1950 printf("\t\tcopy %"PRIu32": %s:%"PRIu16" (status:%s)\n",copy+1,csstrip,cdtab[copy].port,strtype);
1951 }
1952 } else {
1953 if (fileinfomode&FILEINFO_CRC) {
1954 printf("\t\tcopy %"PRIu32": %s:%"PRIu16" (status:%s) - can't get checksum\n",copy+1,csstrip,cdtab[copy].port,strtype);
1955 } else {
1956 printf("\t\tcopy %"PRIu32": %s:%"PRIu16" (status:%s)\n",copy+1,csstrip,cdtab[copy].port,strtype);
1957 }
1958 }
1959 } else {
1960 printf("\t\tcopy %"PRIu32": %s:%"PRIu16" (status:%s)\n",copy+1,csstrip,cdtab[copy].port,strtype);
1961 }
1962 }
1963 if (checksumerror) {
1964 printf("\t\tcopies have different checksums !!!\n");
1965 }
1966 if ((fileinfomode&FILEINFO_SIGNATURE) && firstdigest) {
1967 printf("\t\tcouldn't add this chunk to signature !!!\n");
1968 }
1969 if (vcopies==0) {
1970 printf("\t\tno valid copies !!!\n");
1971 }
1972 if (cdtab!=NULL) {
1973 free(cdtab);
1974 }
1975 }
1976 if (master_end_packet()==0) {
1977 printf("%s: master query: packet size error\n",fname);
1978 return -1;
1979 }
1980 }
1981 if (fileinfomode&FILEINFO_SIGNATURE) {
1982 md5_final(currentdigest,&filectx);
1983 digest_to_str(strdigest,currentdigest);
1984 printf("%s signature: %s\n",fname,strdigest);
1985 }
1986 }
1987 return 0;
1988 }
1989
append_file(const char * fname,const char * afname,int64_t slice_from,int64_t slice_to)1990 int append_file(const char *fname,const char *afname,int64_t slice_from,int64_t slice_to) {
1991 uint32_t inode,ainode,uid,gid;
1992 uint32_t slice_from_abs,slice_to_abs;
1993 uint8_t flags;
1994 gid_t grouplist[NGROUPS_MAX];
1995 uint32_t i,gids;
1996 uint8_t addmaingroup;
1997 mode_t dmode,smode;
1998 uint8_t status;
1999
2000 if (slice_from < INT64_C(-0xFFFFFFFF) || slice_to > INT64_C(0xFFFFFFFF) || slice_to < INT64_C(-0xFFFFFFFF) || slice_to > INT64_C(0xFFFFFFFF)) {
2001 printf("bad slice indexes\n");
2002 return -1;
2003 }
2004 flags = 0;
2005 if (slice_from<0) {
2006 slice_from_abs = -slice_from;
2007 flags |= APPEND_SLICE_FROM_NEG;
2008 } else {
2009 slice_from_abs = slice_from;
2010 }
2011 if (slice_to<0) {
2012 slice_to_abs = -slice_to;
2013 flags |= APPEND_SLICE_TO_NEG;
2014 } else {
2015 slice_to_abs = slice_to;
2016 }
2017
2018 if (master_prepare_conn(fname,&inode,&dmode,NULL,0,1)<0) {
2019 return -1;
2020 }
2021 if (master_prepare_conn(afname,&ainode,&smode,NULL,1,1)<0) {
2022 return -1;
2023 }
2024
2025 if ((slice_from!=0 || slice_to!=0x80000000) && master_get_version()<VERSION2INT(3,0,92)) {
2026 printf("slices not supported in your master - please upgrade it\n");
2027 return -1;
2028 }
2029 if ((smode&S_IFMT)!=S_IFREG) {
2030 printf("%s: not a file\n",afname);
2031 return -1;
2032 }
2033 if ((dmode&S_IFMT)!=S_IFREG) {
2034 printf("%s: not a file\n",fname);
2035 return -1;
2036 }
2037 uid = getuid();
2038 gid = getgid();
2039 if (master_get_version()>=VERSION2INT(2,0,0)) {
2040 gids = getgroups(NGROUPS_MAX,grouplist);
2041 addmaingroup = 1;
2042 for (i=0 ; i<gids ; i++) {
2043 if (grouplist[i]==gid) {
2044 addmaingroup = 0;
2045 }
2046 }
2047 } else {
2048 gids = 0;
2049 addmaingroup = 0;
2050 }
2051 master_new_packet();
2052 if (master_get_version()>=VERSION2INT(3,0,92)) {
2053 master_put8bit(flags);
2054 master_put32bit(inode);
2055 master_put32bit(ainode);
2056 master_put32bit(slice_from_abs);
2057 master_put32bit(slice_to_abs);
2058 } else {
2059 master_put32bit(inode);
2060 master_put32bit(ainode);
2061 }
2062 master_put32bit(uid);
2063 if (master_get_version()<VERSION2INT(2,0,0)) {
2064 master_put32bit(gid);
2065 } else {
2066 master_put32bit(addmaingroup+gids);
2067 if (addmaingroup) {
2068 master_put32bit(gid);
2069 }
2070 for (i=0 ; i<gids ; i++) {
2071 master_put32bit(grouplist[i]);
2072 }
2073 }
2074 if (master_send_and_receive(CLTOMA_FUSE_APPEND_SLICE,MATOCL_FUSE_APPEND_SLICE)<0) {
2075 return -1;
2076 }
2077 if (master_get_leng()!=1) {
2078 printf("%s: master query: wrong answer (leng)\n",fname);
2079 master_error();
2080 return -1;
2081 }
2082 status = master_get8bit();
2083 if (status!=MFS_STATUS_OK) {
2084 printf("%s: %s\n",fname,mfsstrerr(status));
2085 return -1;
2086 }
2087 if (master_end_packet()==0) {
2088 printf("%s: master query: packet size error\n",fname);
2089 return -1;
2090 }
2091 return 0;
2092 }
2093
2094 static uint32_t dirnode_cnt;
2095 static uint32_t filenode_cnt;
2096 static uint32_t touched_inodes;
2097 static uint64_t sumlength;
2098 static uint64_t chunk_size_cnt;
2099 static uint64_t chunk_rsize_cnt;
2100
sc_node_info(uint32_t inode)2101 int sc_node_info(uint32_t inode) {
2102 uint16_t anstype;
2103 uint64_t fleng;
2104 uint64_t chunkid;
2105 uint32_t chunksize;
2106 uint32_t childinode;
2107 uint64_t continueid;
2108 uint8_t copies;
2109
2110 // printf("inode: %"PRIu32"\n",inode);
2111 continueid = 0;
2112 touched_inodes++;
2113 do {
2114 master_new_packet();
2115 master_put32bit(inode);
2116 master_put32bit(500); // 500 !!!
2117 master_put64bit(continueid);
2118 if (master_send_and_receive(CLTOMA_NODE_INFO,MATOCL_NODE_INFO)<0) {
2119 return -1;
2120 }
2121 if (master_get_leng()==1) {
2122 // error - ignore
2123 return 0;
2124 }
2125 if (master_get_leng()<2) {
2126 printf("inode: %"PRIu32" ; master query: wrong answer (size)\n",inode);
2127 master_error();
2128 return -1;
2129 }
2130 anstype = master_get16bit();
2131 if (anstype==1 && ((master_get_leng()-2)%4)==0) { // directory
2132 // printf("directory\n");
2133 if (continueid==0) {
2134 dirnode_cnt++;
2135 }
2136 continueid = master_get64bit();
2137 // printf("continueid: %"PRIX64"\n",continueid);
2138 while (master_bytes_left()>0) {
2139 childinode = master_get32bit();
2140 // printf("inode: %"PRIu32"\n",childinode);
2141 if (sc_enqueue(childinode)==0) {
2142 touched_inodes++; // repeated nodes - increment here
2143 }
2144 }
2145 } else if (anstype==2 && (master_get_leng()-2-16)%13==0) { // file
2146 // printf("file\n");
2147 if (continueid==0) {
2148 filenode_cnt++;
2149 }
2150 continueid = master_get64bit();
2151 fleng = master_get64bit();
2152 // printf("continueid: %"PRIu64" ; fleng: %"PRIu64"\n",continueid,fleng);
2153 sumlength += fleng;
2154 while (master_bytes_left()>0) {
2155 chunkid = master_get64bit();
2156 chunksize = master_get32bit();
2157 copies = master_get8bit();
2158 // printf("chunk: %016"PRIX64" ; chunksize: %"PRIu32" ; copies:%"PRIu8"\n",chunkid,chunksize,copies);
2159 if (liset_addval(chunk_liset,chunkid)==0) { // new chunk ?
2160 chunk_size_cnt += chunksize;
2161 chunk_rsize_cnt += copies * chunksize;
2162 }
2163 }
2164 } else {
2165 continueid = 0;
2166 }
2167 if (master_end_packet()==0) { // pro forma
2168 printf("master query: packet size error\n");
2169 return -1;
2170 }
2171 } while (continueid!=0);
2172 return 0;
2173 }
2174
2175
dir_info(uint8_t dirinfomode,const char * fname)2176 int dir_info(uint8_t dirinfomode,const char *fname) {
2177 uint32_t inode;
2178 uint32_t inodes,dirs,files,chunks;
2179 uint64_t length,size,realsize;
2180
2181 if (master_prepare_conn(fname,&inode,NULL,NULL,0,0)<0) {
2182 return -1;
2183 }
2184 master_new_packet();
2185 master_put32bit(inode);
2186 if (master_send_and_receive(CLTOMA_FUSE_GETDIRSTATS,MATOCL_FUSE_GETDIRSTATS)<0) {
2187 return -1;
2188 }
2189 if (master_get_leng()==1) {
2190 printf("%s: %s\n",fname,mfsstrerr(master_get8bit()));
2191 return -1;
2192 } else if (master_get_leng()!=56 && master_get_leng()!=40) {
2193 printf("%s: master query: wrong answer (leng)\n",fname);
2194 master_error();
2195 return -1;
2196 }
2197 inodes = master_get32bit();
2198 dirs = master_get32bit();
2199 files = master_get32bit();
2200 if (master_get_leng()==56) {
2201 (void)master_get64bit();
2202 }
2203 chunks = master_get32bit();
2204 if (master_get_leng()==56) {
2205 (void)master_get64bit();
2206 }
2207 length = master_get64bit();
2208 size = master_get64bit();
2209 realsize = master_get64bit();
2210 if (dirinfomode==0 || dirinfomode==DIRINFO_PRECISE) {
2211 printf("%s:\n",fname);
2212 print_number(" inodes: ","\n",inodes,0,0,1);
2213 print_number(" directories: ","\n",dirs,0,0,1);
2214 print_number(" files: ","\n",files,0,0,1);
2215 print_number(" chunks: ","\n",chunks,0,0,1);
2216 print_number(" length: ","\n",length,0,1,1);
2217 print_number(" size: ","\n",size,0,1,1);
2218 print_number(" realsize: ","\n",realsize,0,1,1);
2219 } else {
2220 if (dirinfomode&DIRINFO_INODES) {
2221 print_number_only(inodes,0);
2222 printf("\t");
2223 }
2224 if (dirinfomode&DIRINFO_DIRS) {
2225 print_number_only(dirs,0);
2226 printf("\t");
2227 }
2228 if (dirinfomode&DIRINFO_FILES) {
2229 print_number_only(files,0);
2230 printf("\t");
2231 }
2232 if (dirinfomode&DIRINFO_CHUNKS) {
2233 print_number_only(chunks,0);
2234 printf("\t");
2235 }
2236 if (dirinfomode&DIRINFO_LENGTH) {
2237 print_number_only(length,1);
2238 printf("\t");
2239 }
2240 if (dirinfomode&DIRINFO_SIZE) {
2241 print_number_only(size,1);
2242 printf("\t");
2243 }
2244 if (dirinfomode&DIRINFO_REALSIZE) {
2245 print_number_only(realsize,1);
2246 printf("\t");
2247 }
2248 printf("%s\n",fname);
2249 }
2250 if (master_end_packet()==0) {
2251 printf("%s: master query: packet size error\n",fname);
2252 return -1;
2253 }
2254 if (dirinfomode&DIRINFO_PRECISE) {
2255 uint16_t progress;
2256 double seconds,lseconds;
2257 uint8_t err;
2258
2259 if (master_get_version()<VERSION2INT(3,0,73)) {
2260 printf("precise data calculation needs master at least in version 3.0.73 - upgrade your unit\n");
2261 } else {
2262 err = 0;
2263
2264 qhead = NULL;
2265 qtail = &qhead;
2266
2267 dirnode_cnt = 0;
2268 filenode_cnt = 0;
2269 touched_inodes = 0;
2270 sumlength = 0;
2271 chunk_size_cnt = 0;
2272 chunk_rsize_cnt = 0;
2273 lseconds = monotonic_seconds();
2274
2275 inode_liset = liset_new();
2276 chunk_liset = liset_new();
2277 sc_enqueue(inode);
2278 while (sc_dequeue(&inode)) {
2279 if (err==0) {
2280 if (sc_node_info(inode)<0) {
2281 err = 1;
2282 }
2283 progress = ((uint64_t)touched_inodes * 10000ULL) / (uint64_t)inodes;
2284 if (progress>9999) {
2285 progress=9999;
2286 }
2287 seconds = monotonic_seconds();
2288 if (lseconds+0.1<seconds) {
2289 lseconds = seconds;
2290 printf("\r%2u.%02u%% complete ",(unsigned int)(progress/100),(unsigned int)(progress%100));fflush(stdout);
2291 }
2292 }
2293 }
2294 printf("\r");
2295 if (err==0) {
2296 if (dirinfomode==DIRINFO_PRECISE) {
2297 printf("%s (precise data):\n",fname);
2298 print_number(" inodes: ","\n",liset_card(inode_liset),0,0,1);
2299 print_number(" directories: ","\n",dirnode_cnt,0,0,1);
2300 print_number(" files: ","\n",filenode_cnt,0,0,1);
2301 print_number(" chunks: ","\n",liset_card(chunk_liset),0,0,1);
2302 print_number(" length: ","\n",sumlength,0,1,1);
2303 print_number(" size: ","\n",chunk_size_cnt,0,1,1);
2304 print_number(" realsize: ","\n",chunk_rsize_cnt,0,1,1);
2305 } else {
2306 if (dirinfomode&DIRINFO_INODES) {
2307 print_number_only(liset_card(inode_liset),0);
2308 printf("\t");
2309 }
2310 if (dirinfomode&DIRINFO_DIRS) {
2311 print_number_only(dirnode_cnt,0);
2312 printf("\t");
2313 }
2314 if (dirinfomode&DIRINFO_FILES) {
2315 print_number_only(filenode_cnt,0);
2316 printf("\t");
2317 }
2318 if (dirinfomode&DIRINFO_CHUNKS) {
2319 print_number_only(liset_card(chunk_liset),0);
2320 printf("\t");
2321 }
2322 if (dirinfomode&DIRINFO_LENGTH) {
2323 print_number_only(sumlength,1);
2324 printf("\t");
2325 }
2326 if (dirinfomode&DIRINFO_SIZE) {
2327 print_number_only(chunk_size_cnt,1);
2328 printf("\t");
2329 }
2330 if (dirinfomode&DIRINFO_REALSIZE) {
2331 print_number_only(chunk_rsize_cnt,1);
2332 printf("\t");
2333 }
2334 printf("%s (precise data)\n",fname);
2335 }
2336 }
2337 liset_remove(chunk_liset);
2338 liset_remove(inode_liset);
2339 }
2340 }
2341 return 0;
2342 }
2343
file_repair(const char * fname)2344 int file_repair(const char *fname) {
2345 uint32_t inode,uid,gid;
2346 gid_t grouplist[NGROUPS_MAX];
2347 uint32_t i,gids;
2348 uint8_t addmaingroup;
2349 uint32_t notchanged,erased,repaired;
2350
2351 if (master_prepare_conn(fname,&inode,NULL,NULL,0,1)<0) {
2352 return -1;
2353 }
2354 uid = getuid();
2355 gid = getgid();
2356 if (master_get_version()>=VERSION2INT(2,0,0)) {
2357 gids = getgroups(NGROUPS_MAX,grouplist);
2358 addmaingroup = 1;
2359 for (i=0 ; i<gids ; i++) {
2360 if (grouplist[i]==gid) {
2361 addmaingroup = 0;
2362 }
2363 }
2364 } else {
2365 gids = 0;
2366 addmaingroup = 0;
2367 }
2368 master_new_packet();
2369 master_put32bit(inode);
2370 master_put32bit(uid);
2371 if (master_get_version()<VERSION2INT(2,0,0)) {
2372 master_put32bit(gid);
2373 } else {
2374 master_put32bit(addmaingroup+gids);
2375 if (addmaingroup) {
2376 master_put32bit(gid);
2377 }
2378 for (i=0 ; i<gids ; i++) {
2379 master_put32bit(grouplist[i]);
2380 }
2381 }
2382 if (master_send_and_receive(CLTOMA_FUSE_REPAIR,MATOCL_FUSE_REPAIR)<0) {
2383 return -1;
2384 }
2385 if (master_get_leng()==1) {
2386 printf("%s: %s\n",fname,mfsstrerr(master_get8bit()));
2387 return -1;
2388 } else if (master_get_leng()!=12) {
2389 printf("%s: master query: wrong answer (leng)\n",fname);
2390 master_error();
2391 return -1;
2392 }
2393 notchanged = master_get32bit();
2394 erased = master_get32bit();
2395 repaired = master_get32bit();
2396 printf("%s:\n",fname);
2397 print_number(" chunks not changed: ","\n",notchanged,1,0,1);
2398 print_number(" chunks erased: ","\n",erased,1,0,1);
2399 print_number(" chunks repaired: ","\n",repaired,1,0,1);
2400 if (master_end_packet()==0) {
2401 printf("%s: master query: packet size error\n",fname);
2402 return -1;
2403 }
2404 return 0;
2405 }
2406
2407 /*
2408 int eattr_control(const char *fname,uint8_t mode,uint8_t eattr) {
2409 uint8_t reqbuff[22],*wptr,*buff;
2410 const uint8_t *rptr;
2411 uint32_t cmd,leng,inode;
2412 uint8_t nodeeattr,functioneattr;
2413 // uint32_t curinodes;
2414 // uint64_t curlength,cursize,currealsize;
2415 int fd;
2416 fd = open_master_conn(fname,&inode,NULL,NULL,0,(mode<2)?1:0);
2417 if (fd<0) {
2418 return -1;
2419 }
2420 wptr = reqbuff;
2421 put32bit(&wptr,CLTOMA_FUSE_EATTR);
2422 put32bit(&wptr,14);
2423 put32bit(&wptr,0);
2424 put32bit(&wptr,inode);
2425 put32bit(&wptr,getuid());
2426 put8bit(&wptr,mode&1);
2427 put8bit(&wptr,(mode>1)?0:eattr);
2428 if (tcpwrite(fd,reqbuff,22)!=22) {
2429 printf("%s: master query: send error\n",fname);
2430 close_master_conn(1);
2431 return -1;
2432 }
2433 if (tcpread(fd,reqbuff,8)!=8) {
2434 printf("%s: master query: receive error\n",fname);
2435 close_master_conn(1);
2436 return -1;
2437 }
2438 rptr = reqbuff;
2439 cmd = get32bit(&rptr);
2440 leng = get32bit(&rptr);
2441 if (cmd!=MATOCL_FUSE_EATTR) {
2442 printf("%s: master query: wrong answer (type)\n",fname);
2443 close_master_conn(1);
2444 return -1;
2445 }
2446 buff = malloc(leng);
2447 if (tcpread(fd,buff,leng)!=(int32_t)leng) {
2448 printf("%s: master query: receive error\n",fname);
2449 free(buff);
2450 close_master_conn(1);
2451 return -1;
2452 }
2453 rptr = buff;
2454 cmd = get32bit(&rptr); // queryid
2455 if (cmd!=0) {
2456 printf("%s: master query: wrong answer (queryid)\n",fname);
2457 free(buff);
2458 close_master_conn(1);
2459 return -1;
2460 }
2461 leng-=4;
2462 if (leng==1) {
2463 printf("%s: %s\n",fname,mfsstrerr(*rptr));
2464 free(buff);
2465 close_master_conn(1);
2466 return -1;
2467 } else if (leng!=2) {
2468 printf("%s: master query: wrong answer (leng)\n",fname);
2469 free(buff);
2470 close_master_conn(1);
2471 return -1;
2472 }
2473 close_master_conn(0);
2474 nodeeattr = get8bit(&rptr) & eattr;
2475 functioneattr = get8bit(&rptr) & eattr;
2476 free(buff);
2477 printf("%s:",fname);
2478 printf(" nodeeattr:");
2479 if (nodeeattr==0) {
2480 printf("-");
2481 } else {
2482 // as for now there is only one eattr: noowner
2483 if (nodeeattr&EATTR_NOOWNER) {
2484 printf("noowner");
2485 } else {
2486 printf("?");
2487 }
2488 }
2489 printf("; workingeattr:");
2490 if (functioneattr==0) {
2491 printf("-");
2492 } else {
2493 // as for now there is only one eattr: noowner
2494 if (functioneattr&EATTR_NOOWNER) {
2495 printf("noowner");
2496 } else {
2497 printf("?");
2498 }
2499 }
2500 printf("\n");
2501 return 0;
2502 }
2503 */
2504
quota_control(const char * fname,uint8_t mode,uint8_t * qflags,uint32_t * graceperiod,uint32_t * sinodes,uint64_t * slength,uint64_t * ssize,uint64_t * srealsize,uint32_t * hinodes,uint64_t * hlength,uint64_t * hsize,uint64_t * hrealsize)2505 int quota_control(const char *fname,uint8_t mode,uint8_t *qflags,uint32_t *graceperiod,uint32_t *sinodes,uint64_t *slength,uint64_t *ssize,uint64_t *srealsize,uint32_t *hinodes,uint64_t *hlength,uint64_t *hsize,uint64_t *hrealsize) {
2506 uint32_t inode;
2507 uint32_t curinodes;
2508 uint64_t curlength,cursize,currealsize;
2509
2510 // printf("set quota: %s (soft:%1X,i:%"PRIu32",l:%"PRIu64",w:%"PRIu64",r:%"PRIu64"),(hard:%1X,i:%"PRIu32",l:%"PRIu64",w:%"PRIu64",r:%"PRIu64")\n",fname,sflags,sinodes,slength,ssize,srealsize,hflags,hinodes,hlength,hsize,hrealsize);
2511 if (mode==2) {
2512 *qflags = 0;
2513 }
2514 if (master_prepare_conn(fname,&inode,NULL,NULL,0,(*qflags)?1:0)<0) {
2515 return -1;
2516 }
2517 master_new_packet();
2518 master_put32bit(inode);
2519 master_put8bit(*qflags);
2520 if (mode==0) {
2521 if (master_get_version()>=VERSION2INT(3,0,9)) {
2522 master_put32bit(*graceperiod);
2523 }
2524 master_put32bit(*sinodes);
2525 master_put64bit(*slength);
2526 master_put64bit(*ssize);
2527 master_put64bit(*srealsize);
2528 master_put32bit(*hinodes);
2529 master_put64bit(*hlength);
2530 master_put64bit(*hsize);
2531 master_put64bit(*hrealsize);
2532 }
2533 if (master_send_and_receive(CLTOMA_FUSE_QUOTACONTROL,MATOCL_FUSE_QUOTACONTROL)<0) {
2534 return -1;
2535 }
2536 if (master_get_leng()==1) {
2537 printf("%s: %s\n",fname,mfsstrerr(master_get8bit()));
2538 return -1;
2539 } else if (master_get_leng()!=85 && master_get_leng()!=89) {
2540 printf("%s: master query: wrong answer (leng)\n",fname);
2541 master_error();
2542 return -1;
2543 }
2544 *qflags = master_get8bit();
2545 if (master_get_leng()==89) {
2546 *graceperiod = master_get32bit();
2547 } else {
2548 *graceperiod = 0;
2549 }
2550 *sinodes = master_get32bit();
2551 *slength = master_get64bit();
2552 *ssize = master_get64bit();
2553 *srealsize = master_get64bit();
2554 *hinodes = master_get32bit();
2555 *hlength = master_get64bit();
2556 *hsize = master_get64bit();
2557 *hrealsize = master_get64bit();
2558 curinodes = master_get32bit();
2559 curlength = master_get64bit();
2560 cursize = master_get64bit();
2561 currealsize = master_get64bit();
2562 if ((*graceperiod)>0) {
2563 printf("%s: (current values | soft quota | hard quota) ; soft quota grace period: %u seconds\n",fname,*graceperiod);
2564 } else {
2565 printf("%s: (current values | soft quota | hard quota) ; soft quota grace period: default\n",fname);
2566 }
2567 print_number(" inodes | ",NULL,curinodes,0,0,1);
2568 print_number(" | ",NULL,*sinodes,0,0,(*qflags)"A_FLAG_SINODES);
2569 print_number(" | "," |\n",*hinodes,0,0,(*qflags)"A_FLAG_HINODES);
2570 print_number(" length | ",NULL,curlength,0,1,1);
2571 print_number(" | ",NULL,*slength,0,1,(*qflags)"A_FLAG_SLENGTH);
2572 print_number(" | "," |\n",*hlength,0,1,(*qflags)"A_FLAG_HLENGTH);
2573 print_number(" size | ",NULL,cursize,0,1,1);
2574 print_number(" | ",NULL,*ssize,0,1,(*qflags)"A_FLAG_SSIZE);
2575 print_number(" | "," |\n",*hsize,0,1,(*qflags)"A_FLAG_HSIZE);
2576 print_number(" realsize | ",NULL,currealsize,0,1,1);
2577 print_number(" | ",NULL,*srealsize,0,1,(*qflags)"A_FLAG_SREALSIZE);
2578 print_number(" | "," |\n",*hrealsize,0,1,(*qflags)"A_FLAG_HREALSIZE);
2579 if (master_end_packet()==0) {
2580 printf("%s: master query: packet size error\n",fname);
2581 return -1;
2582 }
2583 return 0;
2584 }
2585
2586 /*
2587 int get_quota(const char *fname) {
2588 printf("get quota: %s\n",fname);
2589 return 0;
2590 }
2591
2592 int delete_quota(const char *fname,uint8_t sflags,uint8_t hflags) {
2593 printf("delete quota: %s (soft:%1X,hard:%1X)\n",fname,sflags,hflags);
2594 return 0;
2595 }
2596 */
2597
snapshot_ctl(const char * dstdir,const char * dstbase,const char * srcname,uint32_t srcinode,uint8_t smode)2598 int snapshot_ctl(const char *dstdir,const char *dstbase,const char *srcname,uint32_t srcinode,uint8_t smode) {
2599 uint32_t dstinode,uid,gid;
2600 gid_t grouplist[NGROUPS_MAX];
2601 uint32_t i,gids;
2602 uint8_t addmaingroup;
2603 uint32_t nleng;
2604 uint16_t umsk;
2605 uint8_t status;
2606
2607 umsk = umask(0);
2608 umask(umsk);
2609 nleng = strlen(dstbase);
2610 if (nleng>255) {
2611 printf("%s: name too long\n",dstbase);
2612 return -1;
2613 }
2614 if (master_prepare_conn(dstdir,&dstinode,NULL,NULL,0,1)<0) {
2615 return -1;
2616 }
2617 uid = getuid();
2618 gid = getgid();
2619 if (master_get_version()>=VERSION2INT(2,0,0)) {
2620 gids = getgroups(NGROUPS_MAX,grouplist);
2621 addmaingroup = 1;
2622 for (i=0 ; i<gids ; i++) {
2623 if (grouplist[i]==gid) {
2624 addmaingroup = 0;
2625 }
2626 }
2627 } else {
2628 gids = 0;
2629 addmaingroup = 0;
2630 }
2631 master_new_packet();
2632 master_put32bit(srcinode);
2633 master_put32bit(dstinode);
2634 master_putname(nleng,dstbase);
2635 master_put32bit(uid);
2636 if (master_get_version()<VERSION2INT(2,0,0)) {
2637 master_put32bit(gid);
2638 } else {
2639 master_put32bit(addmaingroup+gids);
2640 if (addmaingroup) {
2641 master_put32bit(gid);
2642 }
2643 for (i=0 ; i<gids ; i++) {
2644 master_put32bit(grouplist[i]);
2645 }
2646 }
2647 master_put8bit(smode);
2648 if (master_get_version()>=VERSION2INT(1,7,0)) {
2649 master_put16bit(umsk);
2650 }
2651 if (master_send_and_receive(CLTOMA_FUSE_SNAPSHOT,MATOCL_FUSE_SNAPSHOT)<0) {
2652 return -1;
2653 }
2654 if (master_get_leng()!=1) {
2655 if (srcname==NULL) {
2656 printf("%s/%s: master query: wrong answer (leng)\n",dstdir,dstbase);
2657 } else {
2658 printf("%s->%s/%s: master query: wrong answer (leng)\n",srcname,dstdir,dstbase);
2659 }
2660 return -1;
2661 }
2662 status = master_get8bit();
2663 if (status!=0) {
2664 if (srcname==NULL) {
2665 printf("%s/%s: %s\n",dstdir,dstbase,mfsstrerr(status));
2666 } else {
2667 printf("%s->%s/%s: %s\n",srcname,dstdir,dstbase,mfsstrerr(status));
2668 }
2669 return -1;
2670 }
2671 if (master_end_packet()==0) {
2672 if (srcname==NULL) {
2673 printf("%s/%s: master query: packet size error\n",dstdir,dstbase);
2674 } else {
2675 printf("%s->%s/%s: master query: packet size error\n",srcname,dstdir,dstbase);
2676 }
2677 return -1;
2678 }
2679 return 0;
2680 }
2681
remove_snapshot(const char * dstname,uint8_t smode)2682 int remove_snapshot(const char *dstname,uint8_t smode) {
2683 char dstpath[PATH_MAX+1],base[PATH_MAX+1],dir[PATH_MAX+1];
2684
2685 if (realpath(dstname,dstpath)==NULL) {
2686 printf("%s: realpath error on %s: %s\n",dstname,dstpath,strerr(errno));
2687 }
2688 memcpy(dir,dstpath,PATH_MAX+1);
2689 dirname_inplace(dir);
2690 if (bsd_basename(dstpath,base)<0) {
2691 printf("%s: basename error\n",dstpath);
2692 return -1;
2693 }
2694 return snapshot_ctl(dir,base,NULL,0,smode | SNAPSHOT_MODE_DELETE);
2695 }
2696
make_snapshot(const char * dstname,char * const * srcnames,uint32_t srcelements,uint8_t smode)2697 int make_snapshot(const char *dstname,char * const *srcnames,uint32_t srcelements,uint8_t smode) {
2698 char to[PATH_MAX+1],base[PATH_MAX+1],dir[PATH_MAX+1];
2699 char src[PATH_MAX+1];
2700 struct stat sst,dst;
2701 int status;
2702 uint32_t i,l;
2703
2704 if (stat(dstname,&dst)<0) { // dst does not exist
2705 if (errno!=ENOENT) {
2706 printf("%s: stat error: %s\n",dstname,strerr(errno));
2707 return -1;
2708 }
2709 if (srcelements>1) {
2710 printf("can snapshot multiple elements only into existing directory\n");
2711 return -1;
2712 }
2713 if (lstat(srcnames[0],&sst)<0) {
2714 printf("%s: lstat error: %s\n",srcnames[0],strerr(errno));
2715 return -1;
2716 }
2717 if (bsd_dirname(dstname,dir)<0) {
2718 printf("%s: dirname error\n",dstname);
2719 return -1;
2720 }
2721 if (stat(dir,&dst)<0) {
2722 printf("%s: stat error: %s\n",dir,strerr(errno));
2723 return -1;
2724 }
2725 if (sst.st_dev != dst.st_dev) {
2726 printf("(%s,%s): both elements must be on the same device\n",dstname,srcnames[0]);
2727 return -1;
2728 }
2729 if (realpath(dir,to)==NULL) {
2730 printf("%s: realpath error on %s: %s\n",dir,to,strerr(errno));
2731 return -1;
2732 }
2733 if (bsd_basename(dstname,base)<0) {
2734 printf("%s: basename error\n",dstname);
2735 return -1;
2736 }
2737 if (strlen(dstname)>0 && dstname[strlen(dstname)-1]=='/' && !S_ISDIR(sst.st_mode)) {
2738 printf("directory %s does not exist\n",dstname);
2739 return -1;
2740 }
2741 return snapshot_ctl(to,base,srcnames[0],sst.st_ino,smode);
2742 } else { // dst exists
2743 if (realpath(dstname,to)==NULL) {
2744 printf("%s: realpath error on %s: %s\n",dstname,to,strerr(errno));
2745 return -1;
2746 }
2747 if (!S_ISDIR(dst.st_mode)) { // dst id not a directory
2748 if (srcelements>1) {
2749 printf("can snapshot multiple elements only into existing directory\n");
2750 return -1;
2751 }
2752 if (lstat(srcnames[0],&sst)<0) {
2753 printf("%s: lstat error: %s\n",srcnames[0],strerr(errno));
2754 return -1;
2755 }
2756 if (sst.st_dev != dst.st_dev) {
2757 printf("(%s,%s): both elements must be on the same device\n",dstname,srcnames[0]);
2758 return -1;
2759 }
2760 memcpy(dir,to,PATH_MAX+1);
2761 dirname_inplace(dir);
2762 // if (bsd_dirname(to,dir)<0) {
2763 // printf("%s: dirname error\n",to);
2764 // return -1;
2765 // }
2766 if (bsd_basename(to,base)<0) {
2767 printf("%s: basename error\n",to);
2768 return -1;
2769 }
2770 return snapshot_ctl(dir,base,srcnames[0],sst.st_ino,smode);
2771 } else { // dst is a directory
2772 status = 0;
2773 for (i=0 ; i<srcelements ; i++) {
2774 if (lstat(srcnames[i],&sst)<0) {
2775 printf("%s: lstat error: %s\n",srcnames[i],strerr(errno));
2776 status=-1;
2777 continue;
2778 }
2779 if (sst.st_dev != dst.st_dev) {
2780 printf("(%s,%s): both elements must be on the same device\n",dstname,srcnames[i]);
2781 status=-1;
2782 continue;
2783 }
2784 if (!S_ISDIR(sst.st_mode)) { // src is not a directory
2785 if (!S_ISLNK(sst.st_mode)) { // src is not a symbolic link
2786 if (realpath(srcnames[i],src)==NULL) {
2787 printf("%s: realpath error on %s: %s\n",srcnames[i],src,strerr(errno));
2788 status=-1;
2789 continue;
2790 }
2791 if (bsd_basename(src,base)<0) {
2792 printf("%s: basename error\n",src);
2793 status=-1;
2794 continue;
2795 }
2796 } else { // src is a symbolic link
2797 if (bsd_basename(srcnames[i],base)<0) {
2798 printf("%s: basename error\n",srcnames[i]);
2799 status=-1;
2800 continue;
2801 }
2802 }
2803 if (snapshot_ctl(to,base,srcnames[i],sst.st_ino,smode)<0) {
2804 status=-1;
2805 }
2806 } else { // src is a directory
2807 l = strlen(srcnames[i]);
2808 if (l>0 && srcnames[i][l-1]!='/') { // src is a directory and name has trailing slash
2809 if (realpath(srcnames[i],src)==NULL) {
2810 printf("%s: realpath error on %s: %s\n",srcnames[i],src,strerr(errno));
2811 status=-1;
2812 continue;
2813 }
2814 if (bsd_basename(src,base)<0) {
2815 printf("%s: basename error\n",src);
2816 status=-1;
2817 continue;
2818 }
2819 if (snapshot_ctl(to,base,srcnames[i],sst.st_ino,smode)<0) {
2820 status=-1;
2821 }
2822 } else { // src is a directory and name has not trailing slash
2823 memcpy(dir,to,PATH_MAX+1);
2824 dirname_inplace(dir);
2825 //if (bsd_dirname(to,dir)<0) {
2826 // printf("%s: dirname error\n",to);
2827 // status=-1;
2828 // continue;
2829 //}
2830 if (bsd_basename(to,base)<0) {
2831 printf("%s: basename error\n",to);
2832 status=-1;
2833 continue;
2834 }
2835 if (snapshot_ctl(dir,base,srcnames[i],sst.st_ino,smode)<0) {
2836 status=-1;
2837 }
2838 }
2839 }
2840 }
2841 return status;
2842 }
2843 }
2844 }
2845
2846 enum {
2847 MFSGETGOAL=1,
2848 MFSSETGOAL,
2849 MFSCOPYGOAL,
2850 MFSGETSCLASS,
2851 MFSSETSCLASS,
2852 MFSXCHGSCLASS,
2853 MFSCOPYSCLASS,
2854 MFSLISTSCLASS,
2855 MFSGETTRASHTIME,
2856 MFSSETTRASHTIME,
2857 MFSCOPYTRASHTIME,
2858 MFSCHECKFILE,
2859 MFSFILEINFO,
2860 MFSAPPENDCHUNKS,
2861 MFSDIRINFO,
2862 MFSFILEREPAIR,
2863 MFSMAKESNAPSHOT,
2864 MFSRMSNAPSHOT,
2865 MFSGETEATTR,
2866 MFSSETEATTR,
2867 MFSDELEATTR,
2868 MFSCOPYEATTR,
2869 MFSGETQUOTA,
2870 MFSSETQUOTA,
2871 MFSDELQUOTA,
2872 MFSCOPYQUOTA,
2873 MFSFILEPATHS,
2874 MFSCHKARCHIVE,
2875 MFSSETARCHIVE,
2876 MFSCLRARCHIVE,
2877 MFSSCADMIN,
2878 MFSMKSC,
2879 MFSCHSC,
2880 MFSRMSC,
2881 MFSCPSC,
2882 MFSMVSC,
2883 MFSLSSC
2884 };
2885
print_numberformat_options()2886 static inline void print_numberformat_options() {
2887 fprintf(stderr," -n - show numbers in plain format\n");
2888 fprintf(stderr," -h - \"human-readable\" numbers using base 2 prefixes (IEC 60027)\n");
2889 fprintf(stderr," -H - \"human-readable\" numbers using base 10 prefixes (SI)\n");
2890 fprintf(stderr," -k - show plain numbers in kibis (binary kilo - 1024)\n");
2891 fprintf(stderr," -m - show plain numbers in mebis (binary mega - 1024^2)\n");
2892 fprintf(stderr," -g - show plain numbers in gibis (binary giga - 1024^3)\n");
2893 }
2894
print_recursive_option()2895 static inline void print_recursive_option() {
2896 fprintf(stderr," -r - do it recursively\n");
2897 }
2898
print_extra_attributes()2899 static inline void print_extra_attributes() {
2900 int j;
2901 fprintf(stderr,"\nattributes:\n");
2902 for (j=0 ; j<EATTR_BITS ; j++) {
2903 if (eattrtab[j][0]) {
2904 fprintf(stderr," %s - %s\n",eattrtab[j],eattrdesc[j]);
2905 }
2906 }
2907 }
2908
usage(int f)2909 void usage(int f) {
2910 switch (f) {
2911 case MFSGETGOAL:
2912 fprintf(stderr,"get objects goal (desired number of copies)\n\nusage: mfsgetgoal [-nhHkmgr] name [name ...]\n");
2913 print_numberformat_options();
2914 print_recursive_option();
2915 break;
2916 case MFSSETGOAL:
2917 fprintf(stderr,"set objects goal (desired number of copies)\n\nusage: mfssetgoal [-nhHkmgr] GOAL[-|+] name [name ...]\n");
2918 print_numberformat_options();
2919 print_recursive_option();
2920 fprintf(stderr," GOAL+ - increase goal to given value\n");
2921 fprintf(stderr," GOAL- - decrease goal to given value\n");
2922 fprintf(stderr," GOAL - just set goal to given value\n");
2923 break;
2924 case MFSCOPYGOAL:
2925 fprintf(stderr,"copy object goal (desired number of copies)\n\nusage: mfscopygoal [-nhHkmgr] srcname dstname [dstname ...]\n");
2926 print_numberformat_options();
2927 print_recursive_option();
2928 break;
2929 case MFSGETSCLASS:
2930 fprintf(stderr,"get objects storage class (desired number of copies / labels)\n\nusage: mfsgetsclass [-nhHkmgr] name [name ...]\n");
2931 print_numberformat_options();
2932 print_recursive_option();
2933 break;
2934 case MFSSETSCLASS:
2935 fprintf(stderr,"set objects storage class (desired number of copies / labels)\n\nusage: mfssetsclass [-nhHkmgr] STORAGE_CLASS_NAME name [name ...]\n");
2936 print_numberformat_options();
2937 print_recursive_option();
2938 break;
2939 case MFSCOPYSCLASS:
2940 fprintf(stderr,"copy object storage class (desired number of copies / labels)\n\nusage: mfscopysclass [-nhHkmgr] srcname dstname [dstname ...]\n");
2941 print_numberformat_options();
2942 print_recursive_option();
2943 break;
2944 case MFSXCHGSCLASS:
2945 fprintf(stderr,"exchange objects storage class (desired number of copies / labels)\n\nusage: mfsxchgsclass [-nhHkmgr] OLD_STORAGE_CLASS_NAME NEW_STORAGE_CLASS_NAME name [name ...]\n");
2946 print_numberformat_options();
2947 print_recursive_option();
2948 break;
2949 case MFSLISTSCLASS:
2950 fprintf(stderr,"lists available storage classes (same as mfsscadmin list)\n\nusage: mfslistsclass [-al] [mountpoint_or_any_subfolder]\n");
2951 fprintf(stderr," -a - lists all storage classes (including standard goal classes)\n");
2952 fprintf(stderr," -l - lists storage classes with definitions (long format)\n");
2953 fprintf(stderr,"If mountpoint_or_any_subfolder is not specified then current directory will be used\n");
2954 break;
2955 case MFSGETTRASHTIME:
2956 fprintf(stderr,"get objects trashtime (how many seconds file should be left in trash)\n\nusage: mfsgettrashtime [-nhHkmgr] name [name ...]\n");
2957 print_numberformat_options();
2958 print_recursive_option();
2959 break;
2960 case MFSSETTRASHTIME:
2961 fprintf(stderr,"set objects trashtime (how many seconds file should be left in trash)\n\nusage: mfssettrashtime [-nhHkmgr] SECONDS[-|+] name [name ...]\n");
2962 print_numberformat_options();
2963 print_recursive_option();
2964 fprintf(stderr," SECONDS+ - increase trashtime to given value\n");
2965 fprintf(stderr," SECONDS- - decrease trashtime to given value\n");
2966 fprintf(stderr," SECONDS - just set trashtime to given value\n");
2967 break;
2968 case MFSCOPYTRASHTIME:
2969 fprintf(stderr,"copy objects trashtime (how many seconds file should be left in trash)\n\nusage: mfscopytrashtime [-nhHkmgr] srcname dstname [dstname ...]\n");
2970 print_numberformat_options();
2971 print_recursive_option();
2972 break;
2973 case MFSCHECKFILE:
2974 fprintf(stderr,"check files\n\nusage: mfscheckfile [-nhHkmg] name [name ...]\n");
2975 break;
2976 case MFSFILEINFO:
2977 fprintf(stderr,"show files info (shows detailed info of each file chunk)\n\nusage: mfsfileinfo [-qcs] name [name ...]\n");
2978 fprintf(stderr,"switches:\n");
2979 fprintf(stderr," -q - quick info (show only number of valid copies)\n");
2980 fprintf(stderr," -c - receive chunk checksums from chunkservers\n");
2981 fprintf(stderr," -s - calculate file signature (using checksums)\n");
2982 break;
2983 case MFSAPPENDCHUNKS:
2984 fprintf(stderr,"append file chunks to another file. If destination file doesn't exist then it's created as empty file and then chunks are appended\n\nusage: mfsappendchunks [-s slice_from:slice_to] dstfile name [name ...]\n");
2985 break;
2986 case MFSDIRINFO:
2987 fprintf(stderr,"show directories stats\n\nusage: mfsdirinfo [-nhHkmg] [-idfclsr] [-p] name [name ...]\n");
2988 print_numberformat_options();
2989 fprintf(stderr,"'show' switches:\n");
2990 fprintf(stderr," -i - show number of inodes\n");
2991 fprintf(stderr," -d - show number of directories\n");
2992 fprintf(stderr," -f - show number of files\n");
2993 fprintf(stderr," -c - show number of chunks\n");
2994 fprintf(stderr," -l - show length\n");
2995 fprintf(stderr," -s - show size\n");
2996 fprintf(stderr," -r - show realsize\n");
2997 fprintf(stderr,"'mode' switch:\n");
2998 fprintf(stderr," -p - precise mode\n");
2999 fprintf(stderr,"\nIf no 'show' switches are present then show everything\n");
3000 fprintf(stderr,"\nMeaning of some not obvious output data:\n 'length' is just sum of files lengths\n 'size' is sum of chunks lengths\n 'realsize' is estimated hdd usage (usually size multiplied by current goal)\n");
3001 fprintf(stderr,"\nPrecise mode means that system takes into account repeated nodes/chunks\nand count them once, also uses current number of copies instead of goal.\n");
3002 break;
3003 case MFSFILEREPAIR:
3004 fprintf(stderr,"repair given file. Use it with caution. It forces file to be readable, so it could erase (fill with zeros) file when chunkservers are not currently connected.\n\nusage: mfsfilerepair [-nhHkmg] name [name ...]\n");
3005 print_numberformat_options();
3006 break;
3007 case MFSMAKESNAPSHOT:
3008 fprintf(stderr,"make snapshot (lazy copy)\n\nusage: mfsmakesnapshot [-ocp] src [src ...] dst\n");
3009 fprintf(stderr," -o - allow to overwrite existing objects\n");
3010 fprintf(stderr," -c - 'cp' mode for attributes (create objects using current uid,gid,umask etc.)\n");
3011 fprintf(stderr," -p - preserve hardlinks\n");
3012 break;
3013 case MFSRMSNAPSHOT:
3014 fprintf(stderr,"remove snapshot (quick rm -r)\n\nusage: mfsrmsnapshot [-f] name [name ...]\n");
3015 fprintf(stderr," -f - remove as much as possible (according to access rights and snapshot flags)\n");
3016 break;
3017 case MFSGETEATTR:
3018 fprintf(stderr,"get objects extra attributes\n\nusage: mfsgeteattr [-nhHkmgr] name [name ...]\n");
3019 print_numberformat_options();
3020 print_recursive_option();
3021 break;
3022 case MFSSETEATTR:
3023 fprintf(stderr,"set objects extra attributes\n\nusage: mfsseteattr [-nhHkmgr] -f attrname [-f attrname ...] name [name ...]\n");
3024 print_numberformat_options();
3025 print_recursive_option();
3026 fprintf(stderr," -f attrname - specify attribute to set\n");
3027 print_extra_attributes();
3028 break;
3029 case MFSDELEATTR:
3030 fprintf(stderr,"delete objects extra attributes\n\nusage: mfsdeleattr [-nhHkmgr] -f attrname [-f attrname ...] name [name ...]\n");
3031 print_numberformat_options();
3032 print_recursive_option();
3033 fprintf(stderr," -f attrname - specify attribute to delete\n");
3034 print_extra_attributes();
3035 break;
3036 case MFSCOPYEATTR:
3037 fprintf(stderr,"copy objects extra attributes\n\nusage: mfscopyeattr [-nhHkmgr] srcname dstname [dstname ...]\n");
3038 print_numberformat_options();
3039 print_recursive_option();
3040 break;
3041 case MFSGETQUOTA:
3042 fprintf(stderr,"get quota for given directory (directories)\n\nusage: mfsgetquota [-nhHkmg] dirname [dirname ...]\n");
3043 print_numberformat_options();
3044 break;
3045 case MFSSETQUOTA:
3046 fprintf(stderr,"set quota for given directory (directories)\n\nusage: mfssetquota [-nhHkmg] [-iI inodes] [-p grace_period] [-lL length] [-sS size] [-rR realsize] dirname [dirname ...]\n");
3047 print_numberformat_options();
3048 fprintf(stderr," -p - set grace period in seconds for soft quota\n");
3049 fprintf(stderr," -i/-I - set soft/hard limit for number of filesystem objects\n");
3050 fprintf(stderr," -l/-L - set soft/hard limit for sum of files lengths\n");
3051 fprintf(stderr," -s/-S - set soft/hard limit for sum of file sizes (chunk sizes)\n");
3052 fprintf(stderr," -r/-R - set soft/hard limit for estimated hdd usage (usually size multiplied by goal)\n");
3053 fprintf(stderr,"\nAll numbers can have decimal point and SI/IEC symbol prefix at the end\ndecimal (SI): (k - 10^3 , M - 10^6 , G - 10^9 , T - 10^12 , P - 10^15 , E - 10^18)\nbinary (IEC 60027): (Ki - 2^10 , Mi - 2^20 , Gi - 2^30 , Ti - 2^40 , Pi - 2^50 , Ei - 2^60 )\n");
3054 break;
3055 case MFSDELQUOTA:
3056 fprintf(stderr,"delete quota for given directory (directories)\n\nusage: mfsdelquota [-nhHkmgailsrAILSR] dirname [dirname ...]\n");
3057 print_numberformat_options();
3058 fprintf(stderr," -i/-I - delete inodes soft/hard quota\n");
3059 fprintf(stderr," -l/-L - delete length soft/hard quota\n");
3060 fprintf(stderr," -s/-S - delete size soft/hard quota\n");
3061 fprintf(stderr," -r/-R - delete real size soft/hard quota\n");
3062 fprintf(stderr," -a/-A - delete all soft/hard quotas\n");
3063 break;
3064 case MFSCOPYQUOTA:
3065 fprintf(stderr,"copy quota settings from one directory to another directory (directories)\n\nusage: mfscopyquota [-nhHkmg] srcdirname dstdirname [dstdirname ...]\n");
3066 print_numberformat_options();
3067 break;
3068 case MFSFILEPATHS:
3069 fprintf(stderr,"show all paths of given files or node numbers\n\nusage: mfsfilepaths name/inode [name/inode ...]\n");
3070 fprintf(stderr,"\nIn case of converting node to path, tool has to be run in mfs-mounted directory\n");
3071 break;
3072 case MFSCHKARCHIVE:
3073 fprintf(stderr,"checks if archive flag is set or not (when directory is specified then command will check it recursivelly)\n\nusage: mfschgarchive [-nhHkmg] name [name ...]\n");
3074 print_numberformat_options();
3075 break;
3076 case MFSSETARCHIVE:
3077 fprintf(stderr,"set archive flags in chunks (recursivelly for directories) - moves files to archive (use 'archive' goal/labels instead of 'keep' goal/labels)\n\nusage: mfssetarchive [-nhHkmg] name [name ...]\n");
3078 print_numberformat_options();
3079 break;
3080 case MFSCLRARCHIVE:
3081 fprintf(stderr,"clear archive flags in chunks (recursivelly for directories) - moves files from archive (use 'keep' goal/labels instead of 'archive' goal/labels) - it also changes ctime, so files will move back to archive after time specified in mfssetgoal\n\nusage: mfsclrarchive [-nhHkmg] name [name ...]\n");
3082 print_numberformat_options();
3083 break;
3084 case MFSSCADMIN:
3085 case MFSMKSC:
3086 case MFSCHSC:
3087 case MFSRMSC:
3088 case MFSCPSC:
3089 case MFSMVSC:
3090 case MFSLSSC:
3091 fprintf(stderr,"mfs storage class admin tool\n\nusage:\n");
3092 fprintf(stderr,"\tmfsscadmin [/mountpoint] create|make [-a admin_only] [-m mode] [-C create_labels] -K keep_labels [-A archive_labels -d archive_delay] sclass [sclass ...]\n");
3093 fprintf(stderr,"\tmfsscadmin [/mountpoint] create|make [-a admin_only] [-m mode] LABELS sclass [sclass ...]\n");
3094 fprintf(stderr,"\tmfsscadmin [/mountpoint] modify|change [-f] [-a admin_only] [-m mode] [-C create_labels] [-K keep_labels] [-A archive_labels] [-d archive_delay] sclass [sclass ...]\n");
3095 fprintf(stderr,"\tmfsscadmin [/mountpoint] delete|remove sclass [sclass ...]\n");
3096 fprintf(stderr,"\tmfsscadmin [/mountpoint] copy|duplicate src_sclass dst_sclass [dst_sclass ...]\n");
3097 fprintf(stderr,"\tmfsscadmin [/mountpoint] rename src_sclass_name dst_sclass_name\n");
3098 fprintf(stderr,"\tmfsscadmin [/mountpoint] list [-l]\n");
3099 fprintf(stderr,"\n");
3100 fprintf(stderr,"create/modify options:\n");
3101 fprintf(stderr," -m - set mode (options are: 'l' for 'loose', 's' for 'strict' and 'd' or not specified for 'default')\n");
3102 fprintf(stderr," 'default' mode: if there are overloaded servers, system will wait for them, but in case of no space available will use other servers (disregarding the labels).\n");
3103 fprintf(stderr," 'strict' mode: the system will wait for overloaded servers, but when there is no space on servers with correct labels then will not use them (return ENOSPC or leave chunk as undergoal).\n");
3104 fprintf(stderr," 'loose' mode: the system will disregard the labels in both cases.\n");
3105 fprintf(stderr," -a - set admin only mode ( 0 - anybody can use this storage class, 1 - only admin can use this storage class ) - by default it set to 0\n");
3106 fprintf(stderr," -C - set labels used for creation chunks - when not specified then 'keep' labels are used\n");
3107 fprintf(stderr," -K - set labels used for keeping chunks - must be specified\n");
3108 fprintf(stderr," -A - set labels used for archiving chunks - when not specified then 'keep' labels are used\n");
3109 fprintf(stderr," -d - set number of days used to switch labels from 'keep' to 'archive' - must be specified when '-A' option is given\n");
3110 fprintf(stderr," -f - force modification of classes 1 to 9 (modify only)\n");
3111 fprintf(stderr,"\n");
3112 fprintf(stderr,"list options:\n");
3113 fprintf(stderr," -l - lists storage classes with definitions (long format)\n");
3114 fprintf(stderr,"\n");
3115 fprintf(stderr,"If '/mountpoint' parameter is not specified then current directory is used (it might be any subfolder of mountpoint).\n");
3116 fprintf(stderr,"All actions but list need 'admin' flag specified in mfsexports.cfg\n");
3117 break;
3118 }
3119 exit(1);
3120 }
3121
main(int argc,char ** argv)3122 int main(int argc,char **argv) {
3123 int l,f,status;
3124 int i,j,found;
3125 int ch;
3126 int longmode = 0;
3127 int snapmode = 0;
3128 int rflag = 0;
3129 uint8_t dirinfomode = 0;
3130 uint8_t fileinfomode = 0;
3131 uint64_t v;
3132 uint8_t eattr = 0,goal = 1,smode = SMODE_SET;
3133 storage_class sc;
3134 uint16_t chgmask = 0;
3135 uint32_t trashtime = 86400;
3136 uint32_t sinodes = 0,hinodes = 0;
3137 uint64_t slength = 0,hlength = 0,ssize = 0,hsize = 0,srealsize = 0,hrealsize = 0;
3138 uint32_t graceperiod = 0;
3139 uint8_t qflags = 0;
3140 uint32_t scnleng;
3141 int64_t slice_from = 0,slice_to = 0x80000000;
3142 char *scadmin_mp = NULL;
3143 char *appendfname = NULL;
3144 char *srcname = NULL;
3145 char *hrformat;
3146 char storage_class_name[256];
3147 char src_storage_class_name[256];
3148 char *p;
3149
3150 memset(&sc,0,sizeof(sc));
3151 sc.mode = SCLASS_MODE_STD;
3152 strerr_init();
3153 master_init();
3154
3155 l = strlen(argv[0]);
3156 #define CHECKNAME(name) ((strcmp(argv[0],name)==0) || (l>(int)(sizeof(name)-1) && strcmp((argv[0])+(l-sizeof(name)),"/" name)==0))
3157
3158 if (CHECKNAME("mfstools")) {
3159 if (argc==2 && strcmp(argv[1],"create")==0) {
3160 fprintf(stderr,"create symlinks\n");
3161 #define SYMLINK(name) if (symlink(argv[0],name)<0) { \
3162 perror("error creating symlink '"name"'"); \
3163 }
3164 SYMLINK("mfsgetgoal")
3165 SYMLINK("mfssetgoal")
3166 SYMLINK("mfscopygoal")
3167 SYMLINK("mfsgetsclass")
3168 SYMLINK("mfssetsclass")
3169 SYMLINK("mfscopysclass")
3170 SYMLINK("mfsxchgsclass")
3171 SYMLINK("mfslistsclass")
3172 SYMLINK("mfsgettrashtime")
3173 SYMLINK("mfssettrashtime")
3174 SYMLINK("mfscopytrashtime")
3175 SYMLINK("mfscheckfile")
3176 SYMLINK("mfsfileinfo")
3177 SYMLINK("mfsappendchunks")
3178 SYMLINK("mfsdirinfo")
3179 SYMLINK("mfsfilerepair")
3180 SYMLINK("mfsmakesnapshot")
3181 SYMLINK("mfsrmsnapshot")
3182 SYMLINK("mfsgeteattr")
3183 SYMLINK("mfsseteattr")
3184 SYMLINK("mfsdeleattr")
3185 SYMLINK("mfscopyeattr")
3186 SYMLINK("mfsgetquota")
3187 SYMLINK("mfssetquota")
3188 SYMLINK("mfsdelquota")
3189 SYMLINK("mfscopyquota")
3190 SYMLINK("mfsfilepaths")
3191 SYMLINK("mfschkarchive")
3192 SYMLINK("mfssetarchive")
3193 SYMLINK("mfsclrarchive")
3194 SYMLINK("mfsscadmin")
3195 // deprecated tools:
3196 SYMLINK("mfsrgetgoal")
3197 SYMLINK("mfsrsetgoal")
3198 SYMLINK("mfsrgettrashtime")
3199 SYMLINK("mfsrsettrashtime")
3200 return 0;
3201 } else if (argc==1) {
3202 fprintf(stderr,"mfs multi tool\n\nusage:\n\tmfstools create - create symlinks (mfs<toolname> -> %s)\n",argv[0]);
3203 fprintf(stderr,"\tmfstools mfs<toolname> ... - work as a given tool\n");
3204 fprintf(stderr,"\ntools:\n");
3205 fprintf(stderr,"\tmfsgetgoal\n\tmfssetgoal\n\tmfscopygoal\n");
3206 fprintf(stderr,"\tmfsgetsclass\n\tmfssetsclass\n\tmfscopysclass\n\tmfsxchgsclass\n\tmfslistsclass\n");
3207 fprintf(stderr,"\tmfsgettrashtime\n\tmfssettrashtime\n\tmfscopytrashtime\n");
3208 fprintf(stderr,"\tmfsgeteattr\n\tmfsseteattr\n\tmfsdeleattr\n\tmfscopyeattr\n");
3209 fprintf(stderr,"\tmfsgetquota\n\tmfssetquota\n\tmfsdelquota\n\tmfscopyquota\n");
3210 fprintf(stderr,"\tmfscheckfile\n\tmfsfileinfo\n\tmfsappendchunks\n\tmfsdirinfo\n");
3211 fprintf(stderr,"\tmfsfilerepair\n\tmfsmakesnapshot\n\tmfsfilepaths\n");
3212 fprintf(stderr,"\tmfschkarchive\n\tmfssetarchive\n\tmfsclrarchive\n");
3213 fprintf(stderr,"\tmfsscadmin\n");
3214 return 1;
3215 }
3216 argv++;
3217 argc--;
3218 l = 0;
3219 }
3220 if (CHECKNAME("mfsscadmin")) {
3221 f = MFSSCADMIN;
3222 if (argc<=1) {
3223 usage(MFSSCADMIN);
3224 } else {
3225 argv++;
3226 argc--;
3227 l = 0;
3228 if (*argv[0]=='/') {
3229 scadmin_mp = *argv;
3230 argv++;
3231 argc--;
3232 if (argc==0) {
3233 fprintf(stderr,"missing command after mountpoint\n\n");
3234 usage(MFSSCADMIN);
3235 }
3236 }
3237 if (CHECKNAME("create")) {
3238 f = MFSMKSC;
3239 } else if (CHECKNAME("make")) {
3240 f = MFSMKSC;
3241 } else if (CHECKNAME("modify")) {
3242 f = MFSCHSC;
3243 } else if (CHECKNAME("change")) {
3244 f = MFSCHSC;
3245 } else if (CHECKNAME("delete")) {
3246 f = MFSRMSC;
3247 } else if (CHECKNAME("remove")) {
3248 f = MFSRMSC;
3249 } else if (CHECKNAME("copy")) {
3250 f = MFSCPSC;
3251 } else if (CHECKNAME("duplicate")) {
3252 f = MFSCPSC;
3253 } else if (CHECKNAME("rename")) {
3254 f = MFSMVSC;
3255 } else if (CHECKNAME("list")) {
3256 f = MFSLSSC;
3257 } else {
3258 fprintf(stderr,"unknown storage class admin command\n\n");
3259 usage(MFSSCADMIN);
3260 }
3261 }
3262 } else if (CHECKNAME("mfsgetgoal")) {
3263 f=MFSGETGOAL;
3264 } else if (CHECKNAME("mfsrgetgoal")) {
3265 f=MFSGETGOAL;
3266 rflag=1;
3267 fprintf(stderr,"deprecated tool - use \"mfsgetgoal -r\"\n");
3268 } else if (CHECKNAME("mfssetgoal")) {
3269 f=MFSSETGOAL;
3270 } else if (CHECKNAME("mfsrsetgoal")) {
3271 f=MFSSETGOAL;
3272 rflag=1;
3273 fprintf(stderr,"deprecated tool - use \"mfssetgoal -r\"\n");
3274 } else if (CHECKNAME("mfscopygoal")) {
3275 f=MFSCOPYGOAL;
3276 } else if (CHECKNAME("mfsgetsclass")) {
3277 f=MFSGETSCLASS;
3278 } else if (CHECKNAME("mfssetsclass")) {
3279 f=MFSSETSCLASS;
3280 } else if (CHECKNAME("mfsxchgsclass")) {
3281 f=MFSXCHGSCLASS;
3282 } else if (CHECKNAME("mfscopysclass")) {
3283 f=MFSCOPYSCLASS;
3284 } else if (CHECKNAME("mfslistsclass")) {
3285 f=MFSLISTSCLASS;
3286 } else if (CHECKNAME("mfsgettrashtime")) {
3287 f=MFSGETTRASHTIME;
3288 } else if (CHECKNAME("mfsrgettrashtime")) {
3289 f=MFSGETTRASHTIME;
3290 rflag=1;
3291 fprintf(stderr,"deprecated tool - use \"mfsgettrashtime -r\"\n");
3292 } else if (CHECKNAME("mfssettrashtime")) {
3293 f=MFSSETTRASHTIME;
3294 } else if (CHECKNAME("mfsrsettrashtime")) {
3295 f=MFSSETTRASHTIME;
3296 rflag=1;
3297 fprintf(stderr,"deprecated tool - use \"mfssettrashtime -r\"\n");
3298 } else if (CHECKNAME("mfscopytrashtime")) {
3299 f=MFSCOPYTRASHTIME;
3300 } else if (CHECKNAME("mfscheckfile")) {
3301 f=MFSCHECKFILE;
3302 } else if (CHECKNAME("mfsfileinfo")) {
3303 f=MFSFILEINFO;
3304 } else if (CHECKNAME("mfsappendchunks")) {
3305 f=MFSAPPENDCHUNKS;
3306 } else if (CHECKNAME("mfsdirinfo")) {
3307 f=MFSDIRINFO;
3308 } else if (CHECKNAME("mfsgeteattr")) {
3309 f=MFSGETEATTR;
3310 } else if (CHECKNAME("mfsseteattr")) {
3311 f=MFSSETEATTR;
3312 } else if (CHECKNAME("mfsdeleattr")) {
3313 f=MFSDELEATTR;
3314 } else if (CHECKNAME("mfscopyeattr")) {
3315 f=MFSCOPYEATTR;
3316 } else if (CHECKNAME("mfsgetquota")) {
3317 f=MFSGETQUOTA;
3318 } else if (CHECKNAME("mfssetquota")) {
3319 f=MFSSETQUOTA;
3320 } else if (CHECKNAME("mfsdelquota")) {
3321 f=MFSDELQUOTA;
3322 } else if (CHECKNAME("mfscopyquota")) {
3323 f=MFSCOPYQUOTA;
3324 } else if (CHECKNAME("mfsfilerepair")) {
3325 f=MFSFILEREPAIR;
3326 } else if (CHECKNAME("mfsmakesnapshot")) {
3327 f=MFSMAKESNAPSHOT;
3328 } else if (CHECKNAME("mfsrmsnapshot")) {
3329 f=MFSRMSNAPSHOT;
3330 } else if (CHECKNAME("mfsfilepaths")) {
3331 f=MFSFILEPATHS;
3332 } else if (CHECKNAME("mfschkarchive")) {
3333 f=MFSCHKARCHIVE;
3334 } else if (CHECKNAME("mfssetarchive")) {
3335 f=MFSSETARCHIVE;
3336 } else if (CHECKNAME("mfsclrarchive")) {
3337 f=MFSCLRARCHIVE;
3338 } else if (CHECKNAME("mfsmksc")) {
3339 f=MFSMKSC;
3340 } else if (CHECKNAME("mfschsc")) {
3341 f=MFSCHSC;
3342 } else if (CHECKNAME("mfsrmsc")) {
3343 f=MFSRMSC;
3344 } else if (CHECKNAME("mfscpsc")) {
3345 f=MFSCPSC;
3346 } else if (CHECKNAME("mfsmvsc")) {
3347 f=MFSMVSC;
3348 } else if (CHECKNAME("mfslssc")) {
3349 f=MFSLSSC;
3350 } else {
3351 fprintf(stderr,"unknown binary name\n");
3352 return 1;
3353 }
3354 // argc--;
3355 // argv++;
3356
3357 hrformat = getenv("MFSHRFORMAT");
3358 if (hrformat) {
3359 if (hrformat[0]>='0' && hrformat[0]<='4') {
3360 humode=hrformat[0]-'0';
3361 }
3362 if (hrformat[0]=='h') {
3363 if (hrformat[1]=='+') {
3364 humode=3;
3365 } else {
3366 humode=1;
3367 }
3368 }
3369 if (hrformat[0]=='H') {
3370 if (hrformat[1]=='+') {
3371 humode=4;
3372 } else {
3373 humode=2;
3374 }
3375 }
3376 }
3377
3378 // parse options
3379 switch (f) {
3380 case MFSMAKESNAPSHOT:
3381 while ((ch=getopt(argc,argv,"ocp"))!=-1) {
3382 switch(ch) {
3383 case 'o':
3384 snapmode |= SNAPSHOT_MODE_CAN_OVERWRITE;
3385 break;
3386 case 'c':
3387 snapmode |= SNAPSHOT_MODE_CPLIKE_ATTR;
3388 break;
3389 case 'p':
3390 snapmode |= SNAPSHOT_MODE_PRESERVE_HARDLINKS;
3391 break;
3392 default:
3393 usage(f);
3394 }
3395 }
3396 argc -= optind;
3397 argv += optind;
3398 if (argc<2) {
3399 usage(f);
3400 }
3401 return make_snapshot(argv[argc-1],argv,argc-1,snapmode);
3402 case MFSRMSNAPSHOT:
3403 while ((ch=getopt(argc,argv,"f"))!=-1) {
3404 switch (ch) {
3405 case 'f':
3406 snapmode |= SNAPSHOT_MODE_FORCE_REMOVAL;
3407 break;
3408 default:
3409 usage(f);
3410 }
3411 }
3412 argc -= optind;
3413 argv += optind;
3414 break;
3415 case MFSCOPYGOAL:
3416 case MFSCOPYSCLASS:
3417 case MFSCOPYTRASHTIME:
3418 case MFSCOPYEATTR:
3419 while ((ch=getopt(argc,argv,"rnhHkmg"))!=-1) {
3420 switch(ch) {
3421 case 'n':
3422 humode=0;
3423 break;
3424 case 'h':
3425 humode=1;
3426 break;
3427 case 'H':
3428 humode=2;
3429 break;
3430 case 'k':
3431 numbermode=1;
3432 break;
3433 case 'm':
3434 numbermode=2;
3435 break;
3436 case 'g':
3437 numbermode=3;
3438 break;
3439 case 'r':
3440 rflag=1;
3441 break;
3442 default:
3443 usage(f);
3444 }
3445 }
3446 argc -= optind;
3447 argv += optind;
3448 if (argc<2) {
3449 usage(f);
3450 }
3451 srcname = *argv;
3452 argc--;
3453 argv++;
3454 break;
3455 case MFSCOPYQUOTA:
3456 while ((ch=getopt(argc,argv,"nhHkmg"))!=-1) {
3457 switch(ch) {
3458 case 'n':
3459 humode=0;
3460 break;
3461 case 'h':
3462 humode=1;
3463 break;
3464 case 'H':
3465 humode=2;
3466 break;
3467 case 'k':
3468 numbermode=1;
3469 break;
3470 case 'm':
3471 numbermode=2;
3472 break;
3473 case 'g':
3474 numbermode=3;
3475 break;
3476 default:
3477 usage(f);
3478 }
3479 }
3480 argc -= optind;
3481 argv += optind;
3482 if (argc<2) {
3483 usage(f);
3484 }
3485 srcname = *argv;
3486 argc--;
3487 argv++;
3488 break;
3489 case MFSSETGOAL:
3490 case MFSSETSCLASS:
3491 case MFSXCHGSCLASS:
3492 while ((ch=getopt(argc,argv,"rnhHkmg"))!=-1) {
3493 switch(ch) {
3494 case 'n':
3495 humode=0;
3496 break;
3497 case 'h':
3498 humode=1;
3499 break;
3500 case 'H':
3501 humode=2;
3502 break;
3503 case 'k':
3504 numbermode=1;
3505 break;
3506 case 'm':
3507 numbermode=2;
3508 break;
3509 case 'g':
3510 numbermode=3;
3511 break;
3512 case 'r':
3513 rflag=1;
3514 break;
3515 default:
3516 usage(f);
3517 }
3518 }
3519 argc -= optind;
3520 argv += optind;
3521 if (argc==0) {
3522 usage(f);
3523 }
3524 if (f==MFSSETGOAL) {
3525 p = argv[0];
3526 // [1-9] | [1-9]+ | [1-9]-
3527 if (p[0]>'0' && p[0]<='9' && (p[1]=='\0' || ((p[1]=='-' || p[1]=='+') && p[2]=='\0'))) {
3528 goal = p[0]-'0';
3529 srcname = NULL;
3530 if (p[1]=='-') {
3531 smode = SMODE_DECREASE;
3532 } else if (p[1]=='+') {
3533 smode = SMODE_INCREASE;
3534 } else {
3535 smode = SMODE_SET;
3536 }
3537 } else {
3538 printf("%s: wrong goal definition\n",p);
3539 usage(f);
3540 }
3541 } else {
3542 goal = 0xFF;
3543 smode = SMODE_SET;
3544 if (f==MFSXCHGSCLASS) {
3545 p = argv[0];
3546 scnleng = strlen(p);
3547 if (scnleng>=256) {
3548 printf("%s: storage class name too long\n",p);
3549 usage(f);
3550 }
3551 memcpy(src_storage_class_name,p,scnleng);
3552 src_storage_class_name[scnleng]=0;
3553 argc--;
3554 argv++;
3555 smode |= SMODE_EXCHANGE;
3556 }
3557 p = argv[0];
3558 scnleng = strlen(p);
3559 if (scnleng>=256) {
3560 printf("%s: storage class name too long\n",p);
3561 usage(f);
3562 }
3563 memcpy(storage_class_name,p,scnleng);
3564 storage_class_name[scnleng]=0;
3565 }
3566 argc--;
3567 argv++;
3568 break;
3569 case MFSGETGOAL:
3570 case MFSGETSCLASS:
3571 case MFSGETTRASHTIME:
3572 case MFSSETTRASHTIME:
3573 case MFSGETEATTR:
3574 while ((ch=getopt(argc,argv,"rnhHkmg"))!=-1) {
3575 switch(ch) {
3576 case 'n':
3577 humode=0;
3578 break;
3579 case 'h':
3580 humode=1;
3581 break;
3582 case 'H':
3583 humode=2;
3584 break;
3585 case 'k':
3586 numbermode=1;
3587 break;
3588 case 'm':
3589 numbermode=2;
3590 break;
3591 case 'g':
3592 numbermode=3;
3593 break;
3594 case 'r':
3595 rflag=1;
3596 break;
3597 default:
3598 usage(f);
3599 }
3600 }
3601 argc -= optind;
3602 argv += optind;
3603 if (f==MFSSETTRASHTIME) {
3604 p = argv[0];
3605 if (argc==0) {
3606 usage(f);
3607 }
3608 if (p[0]>='0' && p[0]<='9') {
3609 trashtime = parse_period(p,&p);
3610 }
3611 while (p[0]==' ') {
3612 p++;
3613 }
3614 if (p[0]=='\0' || ((p[0]=='-' || p[0]=='+') && p[1]=='\0')) {
3615 if (p[0]=='-') {
3616 smode=SMODE_DECREASE;
3617 } else if (p[0]=='+') {
3618 smode=SMODE_INCREASE;
3619 }
3620 } else {
3621 fprintf(stderr,"trashtime should be given as number of seconds optionally folowed by '-' or '+'\n");
3622 usage(f);
3623 }
3624 argc--;
3625 argv++;
3626 }
3627 break;
3628 case MFSSETEATTR:
3629 case MFSDELEATTR:
3630 while ((ch=getopt(argc,argv,"rnhHkmgf:"))!=-1) {
3631 switch(ch) {
3632 case 'n':
3633 humode=0;
3634 break;
3635 case 'h':
3636 humode=1;
3637 break;
3638 case 'H':
3639 humode=2;
3640 break;
3641 case 'k':
3642 numbermode=1;
3643 break;
3644 case 'm':
3645 numbermode=2;
3646 break;
3647 case 'g':
3648 numbermode=3;
3649 break;
3650 case 'r':
3651 rflag=1;
3652 break;
3653 case 'f':
3654 found=0;
3655 for (i=0 ; found==0 && i<EATTR_BITS ; i++) {
3656 if (strcmp(optarg,eattrtab[i])==0) {
3657 found=1;
3658 eattr|=1<<i;
3659 }
3660 }
3661 if (!found) {
3662 fprintf(stderr,"unknown flag\n");
3663 usage(f);
3664 }
3665 break;
3666 default:
3667 usage(f);
3668 }
3669 }
3670 argc -= optind;
3671 argv += optind;
3672 if (eattr==0 && argc>=1) {
3673 if (f==MFSSETEATTR) {
3674 fprintf(stderr,"no attribute(s) to set\n");
3675 } else {
3676 fprintf(stderr,"no attribute(s) to delete\n");
3677 }
3678 usage(f);
3679 }
3680 if (f==MFSSETEATTR) {
3681 smode = SMODE_INCREASE;
3682 } else {
3683 smode = SMODE_DECREASE;
3684 }
3685 break;
3686 case MFSFILEREPAIR:
3687 case MFSGETQUOTA:
3688 case MFSCHECKFILE:
3689 case MFSCHKARCHIVE:
3690 case MFSSETARCHIVE:
3691 case MFSCLRARCHIVE:
3692 while ((ch=getopt(argc,argv,"nhHkmg"))!=-1) {
3693 switch(ch) {
3694 case 'n':
3695 humode=0;
3696 break;
3697 case 'h':
3698 humode=1;
3699 break;
3700 case 'H':
3701 humode=2;
3702 break;
3703 case 'k':
3704 numbermode=1;
3705 break;
3706 case 'm':
3707 numbermode=2;
3708 break;
3709 case 'g':
3710 numbermode=3;
3711 break;
3712 default:
3713 usage(f);
3714 }
3715 }
3716 argc -= optind;
3717 argv += optind;
3718 break;
3719 case MFSFILEINFO:
3720 humode = 0;
3721 numbermode = 0;
3722 while ((ch=getopt(argc,argv,"qcs"))!=-1) {
3723 switch(ch) {
3724 case 'q':
3725 fileinfomode |= FILEINFO_QUICK;
3726 break;
3727 case 'c':
3728 fileinfomode |= FILEINFO_CRC;
3729 break;
3730 case 's':
3731 fileinfomode |= FILEINFO_SIGNATURE;
3732 break;
3733 default:
3734 usage(f);
3735 }
3736 }
3737 argc -= optind;
3738 argv += optind;
3739 break;
3740 case MFSDIRINFO:
3741 while ((ch=getopt(argc,argv,"nhHkmgidfclsrp"))!=-1) {
3742 switch(ch) {
3743 case 'n':
3744 humode=0;
3745 break;
3746 case 'h':
3747 humode=1;
3748 break;
3749 case 'H':
3750 humode=2;
3751 break;
3752 case 'k':
3753 numbermode=1;
3754 break;
3755 case 'm':
3756 numbermode=2;
3757 break;
3758 case 'g':
3759 numbermode=3;
3760 break;
3761 case 'i':
3762 dirinfomode |= DIRINFO_INODES;
3763 break;
3764 case 'd':
3765 dirinfomode |= DIRINFO_DIRS;
3766 break;
3767 case 'f':
3768 dirinfomode |= DIRINFO_FILES;
3769 break;
3770 case 'c':
3771 dirinfomode |= DIRINFO_CHUNKS;
3772 break;
3773 case 'l':
3774 dirinfomode |= DIRINFO_LENGTH;
3775 break;
3776 case 's':
3777 dirinfomode |= DIRINFO_SIZE;
3778 break;
3779 case 'r':
3780 dirinfomode |= DIRINFO_REALSIZE;
3781 break;
3782 case 'p':
3783 dirinfomode |= DIRINFO_PRECISE;
3784 break;
3785 default:
3786 usage(f);
3787 }
3788 }
3789 argc -= optind;
3790 argv += optind;
3791 break;
3792 case MFSSETQUOTA:
3793 if (getuid()) {
3794 fprintf(stderr,"only root can change quota\n");
3795 usage(f);
3796 }
3797 while ((ch=getopt(argc,argv,"nhHkmgp:i:I:l:L:s:S:r:R:"))!=-1) {
3798 switch(ch) {
3799 case 'n':
3800 humode=0;
3801 break;
3802 case 'h':
3803 humode=1;
3804 break;
3805 case 'H':
3806 humode=2;
3807 break;
3808 case 'k':
3809 numbermode=1;
3810 break;
3811 case 'm':
3812 numbermode=2;
3813 break;
3814 case 'g':
3815 numbermode=3;
3816 break;
3817 case 'p':
3818 graceperiod = parse_period(optarg,&p);
3819 if (p[0]!='\0') {
3820 fprintf(stderr,"bad grace period\n");
3821 usage(f);
3822 }
3823 break;
3824 case 'i':
3825 if (my_get_number(optarg,&v,UINT32_MAX,0)<0) {
3826 fprintf(stderr,"bad inodes limit\n");
3827 usage(f);
3828 }
3829 if (qflags & QUOTA_FLAG_SINODES) {
3830 fprintf(stderr,"'soft inodes' quota defined twice\n");
3831 usage(f);
3832 }
3833 sinodes = v;
3834 qflags |= QUOTA_FLAG_SINODES;
3835 break;
3836 case 'I':
3837 if (my_get_number(optarg,&v,UINT32_MAX,0)<0) {
3838 fprintf(stderr,"bad inodes limit\n");
3839 usage(f);
3840 }
3841 if (qflags & QUOTA_FLAG_HINODES) {
3842 fprintf(stderr,"'hard inodes' quota defined twice\n");
3843 usage(f);
3844 }
3845 hinodes = v;
3846 qflags |= QUOTA_FLAG_HINODES;
3847 break;
3848 case 'l':
3849 if (my_get_number(optarg,&v,UINT64_MAX,1)<0) {
3850 fprintf(stderr,"bad length limit\n");
3851 usage(f);
3852 }
3853 if (qflags & QUOTA_FLAG_SLENGTH) {
3854 fprintf(stderr,"'soft length' quota defined twice\n");
3855 usage(f);
3856 }
3857 slength = v;
3858 qflags |= QUOTA_FLAG_SLENGTH;
3859 break;
3860 case 'L':
3861 if (my_get_number(optarg,&v,UINT64_MAX,1)<0) {
3862 fprintf(stderr,"bad length limit\n");
3863 usage(f);
3864 }
3865 if (qflags & QUOTA_FLAG_HLENGTH) {
3866 fprintf(stderr,"'hard length' quota defined twice\n");
3867 usage(f);
3868 }
3869 hlength = v;
3870 qflags |= QUOTA_FLAG_HLENGTH;
3871 break;
3872 case 's':
3873 if (my_get_number(optarg,&v,UINT64_MAX,1)<0) {
3874 fprintf(stderr,"bad size limit\n");
3875 usage(f);
3876 }
3877 if (qflags & QUOTA_FLAG_SSIZE) {
3878 fprintf(stderr,"'soft size' quota defined twice\n");
3879 usage(f);
3880 }
3881 ssize = v;
3882 qflags |= QUOTA_FLAG_SSIZE;
3883 break;
3884 case 'S':
3885 if (my_get_number(optarg,&v,UINT64_MAX,1)<0) {
3886 fprintf(stderr,"bad size limit\n");
3887 usage(f);
3888 }
3889 if (qflags & QUOTA_FLAG_HSIZE) {
3890 fprintf(stderr,"'hard size' quota defined twice\n");
3891 usage(f);
3892 }
3893 hsize = v;
3894 qflags |= QUOTA_FLAG_HSIZE;
3895 break;
3896 case 'r':
3897 if (my_get_number(optarg,&v,UINT64_MAX,1)<0) {
3898 fprintf(stderr,"bad real size limit\n");
3899 usage(f);
3900 }
3901 if (qflags & QUOTA_FLAG_SREALSIZE) {
3902 fprintf(stderr,"'soft realsize' quota defined twice\n");
3903 usage(f);
3904 }
3905 srealsize = v;
3906 qflags |= QUOTA_FLAG_SREALSIZE;
3907 break;
3908 case 'R':
3909 if (my_get_number(optarg,&v,UINT64_MAX,1)<0) {
3910 fprintf(stderr,"bad real size limit\n");
3911 usage(f);
3912 }
3913 if (qflags & QUOTA_FLAG_HREALSIZE) {
3914 fprintf(stderr,"'hard realsize' quota defined twice\n");
3915 usage(f);
3916 }
3917 hrealsize = v;
3918 qflags |= QUOTA_FLAG_HREALSIZE;
3919 break;
3920 default:
3921 usage(f);
3922 }
3923 }
3924 if (qflags==0) {
3925 fprintf(stderr,"quota options not defined\n");
3926 usage(f);
3927 }
3928 argc -= optind;
3929 argv += optind;
3930 break;
3931 case MFSDELQUOTA:
3932 if (getuid()) {
3933 fprintf(stderr,"only root can change quota\n");
3934 usage(f);
3935 }
3936 while ((ch=getopt(argc,argv,"nhHkmgiIlLsSrRaA"))!=-1) {
3937 switch(ch) {
3938 case 'n':
3939 humode=0;
3940 break;
3941 case 'h':
3942 humode=1;
3943 break;
3944 case 'H':
3945 humode=2;
3946 break;
3947 case 'k':
3948 numbermode=1;
3949 break;
3950 case 'm':
3951 numbermode=2;
3952 break;
3953 case 'g':
3954 numbermode=3;
3955 break;
3956 case 'i':
3957 if (qflags & QUOTA_FLAG_SINODES) {
3958 fprintf(stderr,"'soft inodes' option given twice\n");
3959 usage(f);
3960 }
3961 qflags |= QUOTA_FLAG_SINODES;
3962 break;
3963 case 'I':
3964 if (qflags & QUOTA_FLAG_HINODES) {
3965 fprintf(stderr,"'hard inodes' option given twice\n");
3966 usage(f);
3967 }
3968 qflags |= QUOTA_FLAG_HINODES;
3969 break;
3970 case 'l':
3971 if (qflags & QUOTA_FLAG_SLENGTH) {
3972 fprintf(stderr,"'soft length' option given twice\n");
3973 usage(f);
3974 }
3975 qflags |= QUOTA_FLAG_SLENGTH;
3976 break;
3977 case 'L':
3978 if (qflags & QUOTA_FLAG_HLENGTH) {
3979 fprintf(stderr,"'hard length' option given twice\n");
3980 usage(f);
3981 }
3982 qflags |= QUOTA_FLAG_HLENGTH;
3983 break;
3984 case 's':
3985 if (qflags & QUOTA_FLAG_SSIZE) {
3986 fprintf(stderr,"'soft size' option given twice\n");
3987 usage(f);
3988 }
3989 qflags |= QUOTA_FLAG_SSIZE;
3990 break;
3991 case 'S':
3992 if (qflags & QUOTA_FLAG_HSIZE) {
3993 fprintf(stderr,"'hard size' option given twice\n");
3994 usage(f);
3995 }
3996 qflags |= QUOTA_FLAG_HSIZE;
3997 break;
3998 case 'r':
3999 if (qflags & QUOTA_FLAG_SREALSIZE) {
4000 fprintf(stderr,"'soft realsize' option given twice\n");
4001 usage(f);
4002 }
4003 qflags |= QUOTA_FLAG_SREALSIZE;
4004 break;
4005 case 'R':
4006 if (qflags & QUOTA_FLAG_HREALSIZE) {
4007 fprintf(stderr,"'hard realsize' option given twice\n");
4008 usage(f);
4009 }
4010 qflags |= QUOTA_FLAG_HREALSIZE;
4011 break;
4012 case 'a':
4013 if (qflags & QUOTA_FLAG_SALL) {
4014 fprintf(stderr,"'all soft quotas' defined together with other soft quota options\n");
4015 usage(f);
4016 }
4017 qflags |= QUOTA_FLAG_SALL;
4018 break;
4019 case 'A':
4020 if (qflags & QUOTA_FLAG_HALL) {
4021 fprintf(stderr,"'all hard quotas' defined together with other hard quota options\n");
4022 usage(f);
4023 }
4024 qflags |= QUOTA_FLAG_HALL;
4025 break;
4026 default:
4027 usage(f);
4028 }
4029 }
4030 if (qflags==0) {
4031 fprintf(stderr,"quota options not defined\n");
4032 usage(f);
4033 }
4034 argc -= optind;
4035 argv += optind;
4036 break;
4037 case MFSMKSC:
4038 case MFSCHSC:
4039 while ((ch=getopt(argc,argv,(f==MFSCHSC)?"d:A:K:C:m:a:f":"d:A:K:C:m:a:"))!=-1) {
4040 switch (ch) {
4041 case 'd':
4042 if (chgmask & SCLASS_CHG_ARCH_DELAY) {
4043 fprintf(stderr,"option '-d' defined more than once\n");
4044 usage(f);
4045 }
4046 sc.arch_delay = strtoul(optarg,NULL,10);
4047 chgmask |= SCLASS_CHG_ARCH_DELAY;
4048 break;
4049 case 'A':
4050 if (chgmask & SCLASS_CHG_ARCH_MASKS) {
4051 fprintf(stderr,"option '-A' defined more than once\n");
4052 usage(f);
4053 }
4054 if (parse_label_expr(optarg,&(sc.arch_labelscnt),sc.arch_labelmasks)<0) {
4055 usage(f);
4056 }
4057 chgmask |= SCLASS_CHG_ARCH_MASKS;
4058 break;
4059 case 'K':
4060 if (chgmask & SCLASS_CHG_KEEP_MASKS) {
4061 fprintf(stderr,"option '-K' defined more than once\n");
4062 usage(f);
4063 }
4064 if (parse_label_expr(optarg,&(sc.keep_labelscnt),sc.keep_labelmasks)<0) {
4065 usage(f);
4066 }
4067 chgmask |= SCLASS_CHG_KEEP_MASKS;
4068 break;
4069 case 'C':
4070 if (chgmask & SCLASS_CHG_CREATE_MASKS) {
4071 fprintf(stderr,"option '-C' defined more than once\n");
4072 usage(f);
4073 }
4074 if (parse_label_expr(optarg,&(sc.create_labelscnt),sc.create_labelmasks)<0) {
4075 usage(f);
4076 }
4077 chgmask |= SCLASS_CHG_CREATE_MASKS;
4078 break;
4079 case 'm':
4080 if (chgmask & SCLASS_CHG_MODE) {
4081 fprintf(stderr,"option '-m' defined more than once\n");
4082 usage(f);
4083 }
4084 if (optarg[0]=='l' || optarg[0]=='L') {
4085 sc.mode = SCLASS_MODE_LOOSE;
4086 } else if (optarg[0]=='s' || optarg[0]=='S') {
4087 sc.mode = SCLASS_MODE_STRICT;
4088 } else if (optarg[0]=='d' || optarg[0]=='D') {
4089 sc.mode = SCLASS_MODE_STD;
4090 } else {
4091 fprintf(stderr,"unknown create mode (option '-m')\n");
4092 usage(f);
4093 }
4094 chgmask |= SCLASS_CHG_MODE;
4095 break;
4096 case 'a':
4097 if (chgmask & SCLASS_CHG_ADMIN_ONLY) {
4098 fprintf(stderr,"option '-a' defined more than once\n");
4099 usage(f);
4100 }
4101 if (optarg[0]=='0' || optarg[0]=='n' || optarg[0]=='N' || optarg[0]=='f' || optarg[0]=='F') {
4102 sc.admin_only = 0;
4103 } else if (optarg[0]=='1' || optarg[0]=='y' || optarg[0]=='Y' || optarg[0]=='t' || optarg[0]=='T') {
4104 sc.admin_only = 1;
4105 } else {
4106 fprintf(stderr,"unknown value for admin only flag (option '-a')\n");
4107 usage(f);
4108 }
4109 chgmask |= SCLASS_CHG_ADMIN_ONLY;
4110 break;
4111 case 'f':
4112 if (chgmask & SCLASS_CHG_FORCE) {
4113 fprintf(stderr,"option '-f' defined more than once\n");
4114 usage(f);
4115 }
4116 chgmask |= SCLASS_CHG_FORCE;
4117 break;
4118 default:
4119 usage(f);
4120 }
4121 }
4122 argc -= optind;
4123 argv += optind;
4124 if (f==MFSMKSC) {
4125 if ((chgmask & (SCLASS_CHG_ARCH_MASKS|SCLASS_CHG_KEEP_MASKS|SCLASS_CHG_CREATE_MASKS)) == 0) {
4126 if (argc<2) {
4127 usage(f);
4128 }
4129 if (parse_label_expr(argv[0],&(sc.create_labelscnt),sc.create_labelmasks)<0) {
4130 usage(f);
4131 }
4132 argc--;
4133 argv++;
4134 sc.keep_labelscnt = sc.create_labelscnt;
4135 sc.arch_labelscnt = sc.create_labelscnt;
4136 for (i=0 ; i<sc.create_labelscnt ; i++) {
4137 for (j=0 ; j<MASKORGROUP ; j++) {
4138 sc.arch_labelmasks[i][j] = sc.keep_labelmasks[i][j] = sc.create_labelmasks[i][j];
4139 }
4140 }
4141 } else {
4142 if ((chgmask & SCLASS_CHG_ARCH_MASKS) && ((chgmask & SCLASS_CHG_KEEP_MASKS)==0)) {
4143 fprintf(stderr,"option '-A' without '-K'\n");
4144 usage(f);
4145 }
4146 if ((chgmask & SCLASS_CHG_CREATE_MASKS) && ((chgmask & SCLASS_CHG_KEEP_MASKS)==0)) {
4147 fprintf(stderr,"option '-C' without '-K'\n");
4148 usage(f);
4149 }
4150 if ((chgmask & SCLASS_CHG_ARCH_MASKS) && ((chgmask & SCLASS_CHG_ARCH_DELAY)==0)) {
4151 fprintf(stderr,"option '-A' without '-d'\n");
4152 usage(f);
4153 }
4154 if ((chgmask & SCLASS_CHG_ARCH_DELAY) && ((chgmask & SCLASS_CHG_ARCH_MASKS)==0)) {
4155 fprintf(stderr,"option '-A' without '-d'\n");
4156 usage(f);
4157 }
4158 if ((chgmask & SCLASS_CHG_KEEP_MASKS) && ((chgmask & SCLASS_CHG_ARCH_MASKS)==0)) {
4159 sc.arch_labelscnt = sc.keep_labelscnt;
4160 for (i=0 ; i<sc.keep_labelscnt ; i++) {
4161 for (j=0 ; j<MASKORGROUP ; j++) {
4162 sc.arch_labelmasks[i][j] = sc.keep_labelmasks[i][j];
4163 }
4164 }
4165 }
4166 if ((chgmask & SCLASS_CHG_KEEP_MASKS) && ((chgmask & SCLASS_CHG_CREATE_MASKS)==0)) {
4167 sc.create_labelscnt = sc.keep_labelscnt;
4168 for (i=0 ; i<sc.keep_labelscnt ; i++) {
4169 for (j=0 ; j<MASKORGROUP ; j++) {
4170 sc.create_labelmasks[i][j] = sc.keep_labelmasks[i][j];
4171 }
4172 }
4173 }
4174 }
4175 }
4176 break;
4177 case MFSCPSC:
4178 if (getopt(argc,argv,"")!=-1) {
4179 usage(f);
4180 }
4181 argc -= optind;
4182 argv += optind;
4183 if (argc<2) {
4184 usage(f);
4185 }
4186 srcname = *argv;
4187 argc--;
4188 argv++;
4189 break;
4190 case MFSMVSC:
4191 if (getopt(argc,argv,"")!=-1) {
4192 usage(f);
4193 }
4194 argc -= optind;
4195 argv += optind;
4196 if (argc!=2) {
4197 usage(f);
4198 }
4199 return move_sc(scadmin_mp,argv[0],argv[1]);
4200 case MFSLSSC:
4201 case MFSLISTSCLASS:
4202 while ((ch=getopt(argc,argv,"l"))!=-1) {
4203 switch(ch) {
4204 case 'l':
4205 longmode |= 1;
4206 break;
4207 default:
4208 usage(f);
4209 }
4210 }
4211 argc -= optind;
4212 argv += optind;
4213 if (f==MFSLISTSCLASS) {
4214 if (argc==1) {
4215 scadmin_mp = *argv;
4216 } else if (argc>1) {
4217 usage(f);
4218 }
4219 } else {
4220 if (argc>0) {
4221 usage(f);
4222 }
4223 }
4224 return list_sc(scadmin_mp,longmode);
4225 case MFSAPPENDCHUNKS:
4226 while ((ch=getopt(argc,argv,"s:"))!=-1) {
4227 switch(ch) {
4228 case 's':
4229 if (parse_slice_expr(optarg,&slice_from,&slice_to)<0) {
4230 usage(f);
4231 }
4232 break;
4233 default:
4234 usage(f);
4235 }
4236 }
4237 argc -= optind;
4238 argv += optind;
4239 break;
4240 case MFSRMSC:
4241 default:
4242 if (getopt(argc,argv,"")!=-1) {
4243 usage(f);
4244 }
4245 argc -= optind;
4246 argv += optind;
4247 // argc--; // skip appname
4248 // argv++;
4249 }
4250
4251 if (f==MFSAPPENDCHUNKS) {
4252 if (argc<=1) {
4253 usage(f);
4254 }
4255 appendfname = argv[0];
4256 i = open(appendfname,O_RDWR | O_CREAT,0666);
4257 if (i<0) {
4258 fprintf(stderr,"can't create/open file: %s\n",appendfname);
4259 return 1;
4260 }
4261 close(i);
4262 argc--;
4263 argv++;
4264 }
4265
4266 if (argc<1) {
4267 usage(f);
4268 }
4269 status=0;
4270 if (f==MFSCOPYGOAL || f==MFSCOPYSCLASS) {
4271 if (get_sclass(srcname,&goal,storage_class_name,GMODE_NORMAL)<0) {
4272 return 1;
4273 }
4274 smode = SMODE_SET;
4275 } else if (f==MFSCOPYTRASHTIME) {
4276 if (get_trashtime(srcname,&trashtime,GMODE_NORMAL)<0) {
4277 return 1;
4278 }
4279 smode = SMODE_SET;
4280 } else if (f==MFSCOPYEATTR) {
4281 if (get_eattr(srcname,&eattr,GMODE_NORMAL)<0) {
4282 return 1;
4283 }
4284 smode = SMODE_SET;
4285 } else if (f==MFSCOPYQUOTA) {
4286 if (quota_control(srcname,2,&qflags,&graceperiod,&sinodes,&slength,&ssize,&srealsize,&hinodes,&hlength,&hsize,&hrealsize)<0) {
4287 return 1;
4288 }
4289 }
4290 while (argc>0) {
4291 switch (f) {
4292 case MFSGETGOAL:
4293 case MFSGETSCLASS:
4294 if (get_sclass(*argv,&goal,storage_class_name,(rflag)?GMODE_RECURSIVE:GMODE_NORMAL)<0) {
4295 status = 1;
4296 }
4297 break;
4298 case MFSSETGOAL:
4299 case MFSSETSCLASS:
4300 case MFSCOPYGOAL:
4301 case MFSCOPYSCLASS:
4302 case MFSXCHGSCLASS:
4303 if (set_sclass(*argv,goal,src_storage_class_name,storage_class_name,(rflag)?(smode | SMODE_RMASK):smode)<0) {
4304 status = 1;
4305 }
4306 break;
4307 case MFSGETTRASHTIME:
4308 if (get_trashtime(*argv,&trashtime,(rflag)?GMODE_RECURSIVE:GMODE_NORMAL)<0) {
4309 status = 1;
4310 }
4311 break;
4312 case MFSSETTRASHTIME:
4313 case MFSCOPYTRASHTIME:
4314 if (set_trashtime(*argv,trashtime,(rflag)?(smode | SMODE_RMASK):smode)<0) {
4315 status = 1;
4316 }
4317 break;
4318 case MFSCHECKFILE:
4319 if (file_info(FILEINFO_QUICK,*argv)<0) {
4320 status = 1;
4321 }
4322 break;
4323 case MFSFILEINFO:
4324 if (file_info(fileinfomode,*argv)<0) {
4325 status = 1;
4326 }
4327 break;
4328 case MFSAPPENDCHUNKS:
4329 if (append_file(appendfname,*argv,slice_from,slice_to)<0) {
4330 status = 1;
4331 }
4332 break;
4333 case MFSDIRINFO:
4334 if (dir_info(dirinfomode,*argv)<0) {
4335 status = 1;
4336 }
4337 break;
4338 case MFSFILEREPAIR:
4339 if (file_repair(*argv)<0) {
4340 status = 1;
4341 }
4342 break;
4343 case MFSGETEATTR:
4344 if (get_eattr(*argv,&eattr,(rflag)?GMODE_RECURSIVE:GMODE_NORMAL)<0) {
4345 status = 1;
4346 }
4347 break;
4348 case MFSSETEATTR:
4349 case MFSDELEATTR:
4350 case MFSCOPYEATTR:
4351 if (set_eattr(*argv,eattr,(rflag)?(smode | SMODE_RMASK):smode)<0) {
4352 status = 1;
4353 }
4354 break;
4355 case MFSGETQUOTA:
4356 if (quota_control(*argv,2,&qflags,&graceperiod,&sinodes,&slength,&ssize,&srealsize,&hinodes,&hlength,&hsize,&hrealsize)<0) {
4357 status = 1;
4358 }
4359 break;
4360 case MFSSETQUOTA:
4361 case MFSCOPYQUOTA:
4362 if (quota_control(*argv,0,&qflags,&graceperiod,&sinodes,&slength,&ssize,&srealsize,&hinodes,&hlength,&hsize,&hrealsize)<0) {
4363 status = 1;
4364 }
4365 break;
4366 case MFSDELQUOTA:
4367 if (quota_control(*argv,1,&qflags,&graceperiod,&sinodes,&slength,&ssize,&srealsize,&hinodes,&hlength,&hsize,&hrealsize)<0) {
4368 status = 1;
4369 }
4370 break;
4371 case MFSFILEPATHS:
4372 if (file_paths(*argv)<0) {
4373 status = 1;
4374 }
4375 break;
4376 case MFSCHKARCHIVE:
4377 if (archive_control(*argv,ARCHCTL_GET)<0) {
4378 status = 1;
4379 }
4380 break;
4381 case MFSSETARCHIVE:
4382 if (archive_control(*argv,ARCHCTL_SET)<0) {
4383 status = 1;
4384 }
4385 break;
4386 case MFSCLRARCHIVE:
4387 if (archive_control(*argv,ARCHCTL_CLR)<0) {
4388 status = 1;
4389 }
4390 break;
4391 case MFSRMSNAPSHOT:
4392 if (remove_snapshot(*argv,snapmode)<0) {
4393 status = 1;
4394 }
4395 break;
4396 case MFSMKSC:
4397 if (make_sc(scadmin_mp,*argv,&sc)<0) {
4398 status = 1;
4399 }
4400 break;
4401 case MFSCHSC:
4402 if (change_sc(scadmin_mp,*argv,chgmask,&sc)<0) {
4403 status = 1;
4404 }
4405 break;
4406 case MFSRMSC:
4407 if (remove_sc(scadmin_mp,*argv)<0) {
4408 status = 1;
4409 }
4410 break;
4411 case MFSCPSC:
4412 if (copy_sc(scadmin_mp,srcname,*argv)<0) {
4413 status = 1;
4414 }
4415 break;
4416 }
4417 argc--;
4418 argv++;
4419 }
4420 return status;
4421 }
4422