hammer2 - Merge Daniel Flores's HAMMER2 GSOC project into the main tree
[dragonfly.git] / sbin / hammer2 / cmd_setcomp.c
1 /*
2  * Copyright (c) 2013 The DragonFly Project.  All rights reserved.
3  *
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  * 3. Neither the name of The DragonFly Project nor the names of its
16  *    contributors may be used to endorse or promote products derived
17  *    from this software without specific, prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
23  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32
33 #include "hammer2.h"
34  
35 int
36 cmd_setcomp(char* comp_string, char* file_string)
37 {
38         int comp_method;
39         if (strcmp(comp_string, "0") == 0) {
40                 printf("Will turn off compression on directory/file %s\n", file_string);
41                 comp_method = HAMMER2_COMP_NONE;
42         } else if (strcmp(comp_string, "1") == 0) {
43                 printf("Will set zero-checking compression on directory/file %s.\n",
44                         file_string);
45                 comp_method = HAMMER2_COMP_AUTOZERO;
46         } else if (strcmp(comp_string, "2") == 0) {
47                 printf("Will set LZ4 compression on directory/file %s.\n", file_string);
48                 comp_method = HAMMER2_COMP_LZ4;
49         } else if (strcmp(comp_string, "3:6") == 0) {
50                 printf("Will set ZLIB level 6 compression on directory/file %s.\n", file_string);
51                 comp_method = 6 << 4;
52                 comp_method += HAMMER2_COMP_ZLIB;
53         } else if (strcmp(comp_string, "3") == 0 || strcmp(comp_string, "3:7") == 0) {
54                 printf("Will set ZLIB level 7 (default) compression on directory/file %s.\n", file_string);
55                 comp_method = 7 << 4;
56                 comp_method += HAMMER2_COMP_ZLIB;
57         } else if (strcmp(comp_string, "3:8") == 0) {
58                 printf("Will set ZLIB level 8 compression on directory/file %s.\n", file_string);
59                 comp_method = 8 << 4;
60                 comp_method += HAMMER2_COMP_ZLIB;
61         } else if (strcmp(comp_string, "3:9") == 0) {
62                 printf("Will set ZLIB level 9 compression on directory/file %s.\n", file_string);
63                 printf("CAUTION: May be extremely slow on big amount of data.\n");
64                 comp_method = 9 << 4;
65                 comp_method += HAMMER2_COMP_ZLIB;
66         } else if (strcmp(comp_string, "3:5") == 0 || strcmp(comp_string, "3:4") == 0 ||
67                                 strcmp(comp_string, "3:3") == 0 || strcmp(comp_string, "3:2") == 0 ||
68                                 strcmp(comp_string, "3:1") == 0) {
69                 printf("ZLIB compression levels below 6 are not supported,\n");
70                 printf("please use LZ4 (setcomp 2) for fast compression instead.\n");
71                 return 1;
72         }
73         else {
74                 printf("ERROR: Unknown compression method.\n");
75                 return 1;
76         }
77         int fd = hammer2_ioctl_handle(file_string);
78         hammer2_ioc_inode_t inode;
79         int res = ioctl(fd, HAMMER2IOC_INODE_GET, &inode);
80         if (res < 0) {
81                 fprintf(stderr, "ERROR before setting the mode: %s\n",
82                         strerror(errno));
83                 return 3;
84         }
85         inode.ip_data.comp_algo = comp_method & 0x0FF;
86         res = ioctl(fd, HAMMER2IOC_INODE_SET, &inode);
87         if (res < 0) {
88                 if (errno != EINVAL) {
89                         fprintf(stderr, "ERROR after trying to set the mode: %s\n",
90                                 strerror(errno));
91                         return 3;
92                 }
93         }
94         close(fd);
95         return 0;
96 }
97
98 int
99 cmd_setcomp_recursive(char* option_string, char* comp_string, char* file_string)
100 {
101         int ecode = 0;
102         int set_files;
103         if (strcmp(option_string, "-r") == 0) {
104                 set_files = 0;
105         }
106         else if (strcmp(option_string, "-rf") == 0) {
107                 set_files = 1;
108         }
109         else {
110                 printf("setcomp: Unrecognized option.\n");
111                 exit(1);
112         }
113         int comp_method;
114         if (strcmp(comp_string, "0") == 0) {
115                 printf("Will turn off compression on directory/file %s\n", file_string);
116                 comp_method = HAMMER2_COMP_NONE;
117         } else if (strcmp(comp_string, "1") == 0) {
118                 printf("Will set zero-checking compression on directory/file %s.\n", file_string);
119                 comp_method = HAMMER2_COMP_AUTOZERO;
120         } else if (strcmp(comp_string, "2") == 0) {
121                 printf("Will set LZ4 compression on directory/file %s.\n", file_string);
122                 comp_method = HAMMER2_COMP_LZ4;
123         } else if (strcmp(comp_string, "3") == 0) {
124                 printf("Will set ZLIB (slowest) compression on directory/file %s.\n", file_string);
125                 comp_method = HAMMER2_COMP_ZLIB;
126         }
127         else {
128                 printf("Unknown compression method.\n");
129                 return 1;
130         }
131         int fd = hammer2_ioctl_handle(file_string);
132         hammer2_ioc_inode_t inode;
133         int res = ioctl(fd, HAMMER2IOC_INODE_GET, &inode);
134         if (res < 0) {
135                 fprintf(stderr, "ERROR before setting the mode: %s\n", strerror(errno));
136                 return 3;
137         }
138         if (inode.ip_data.type != HAMMER2_OBJTYPE_DIRECTORY) {
139                 printf("setcomp: the specified object is not a directory, nothing changed.\n");
140                 return 1;
141         }
142         printf("Attention: recursive compression mode setting demanded, this may take a while...\n");
143         ecode = setcomp_recursive_call(file_string, comp_method, set_files);
144         inode.ip_data.comp_algo = comp_method;
145         res = ioctl(fd, HAMMER2IOC_INODE_SET, &inode);
146         if (res < 0) {
147                 if (errno != EINVAL) {
148                         fprintf(stderr, "ERROR after trying to set the mode: %s\n", strerror(errno));
149                         return 3;
150                 }
151         }
152         close(fd);
153         return ecode;
154 }
155
156 int
157 setcomp_recursive_call(char *directory, int comp_method, int set_files)
158 {
159         int ecode = 0;
160         DIR *dir;
161         if ((dir = opendir (directory)) == NULL) {
162         fprintf(stderr, "ERROR while trying to set the mode recursively: %s\n",
163                         strerror(errno));
164                 return 3;
165     }
166     struct dirent *dent;
167     int lenght;
168     lenght = strlen(directory);
169     char name[HAMMER2_INODE_MAXNAME];
170     strcpy(name, directory);
171     name[lenght] = '/';
172     ++lenght;
173     errno = 0;
174     dent = readdir(dir);
175     while (dent != NULL && ecode == 0) {
176                 if ((strcmp(dent->d_name, ".") != 0) &&
177                  (strcmp(dent->d_name, "..") != 0)) {
178                         strncpy(name + lenght, dent->d_name, HAMMER2_INODE_MAXNAME -
179                                 lenght);
180                         int fd = hammer2_ioctl_handle(name);
181                         hammer2_ioc_inode_t inode;
182                         int res = ioctl(fd, HAMMER2IOC_INODE_GET, &inode);
183                         if (res < 0) {
184                                 fprintf(stderr, "ERROR during recursion: %s\n",
185                                         strerror(errno));
186                                 return 3;
187                         }
188                         if (inode.ip_data.type == HAMMER2_OBJTYPE_DIRECTORY) {
189                                 ecode = setcomp_recursive_call(name, comp_method, set_files);
190                                 inode.ip_data.comp_algo = comp_method;
191                                 res = ioctl(fd, HAMMER2IOC_INODE_SET, &inode);
192                         }
193                         else {
194                                 if (set_files == 1 && inode.ip_data.type ==
195                                                 HAMMER2_OBJTYPE_REGFILE) {
196                                         inode.ip_data.comp_algo = comp_method;
197                                         res = ioctl(fd, HAMMER2IOC_INODE_SET, &inode);
198                                 }
199                         }
200                         if (res < 0) {
201                                 if (errno != EINVAL) {
202                                         fprintf(stderr, "ERROR during recursion after trying"
203                                                 "to set the mode: %s\n",
204                                                 strerror(errno));
205                                         return 3;
206                                 }
207                         }
208                         close(fd);
209                 }
210                 errno = 0; //we must set errno to 0 before readdir()
211                 dent = readdir(dir);
212         }
213         closedir(dir);
214         if (errno != 0) {
215                 fprintf(stderr, "ERROR during iteration: %s\n", strerror(errno));
216                 return 3;
217     }
218     return ecode;
219 }