gdb - Local mods (compile)
[dragonfly.git] / sbin / hammer2 / cmd_setcomp.c
1 /*
2  * Copyright (c) 2013 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@dragonflybsd.org>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34
35 #include "hammer2.h"
36
37 static int cmd_setcomp_core(uint8_t comp_algo, const char *path_str,
38                             struct stat *st);
39  
40 int
41 cmd_setcomp(const char *comp_str, char **paths)
42 {
43         static const char *comps[] = HAMMER2_COMP_STRINGS;
44         struct stat st;
45         int comp_algo;
46         int comp_level;
47         int ecode;
48         int res;
49         char *str;
50         const char *s1;
51         const char *s2;
52
53         str = strdup(comp_str);
54         s1 = strtok(str, ":");
55         s2 = s1 ? strtok(NULL, ":") : NULL;
56         ecode = 0;
57
58         if (isdigit(s1[0])) {
59                 comp_algo = strtol(s1, NULL, 0);
60         } else {
61                 comp_algo = HAMMER2_COMP_STRINGS_COUNT;
62                 while (--comp_algo >= 0) {
63                         if (strcasecmp(s1, comps[comp_algo]) == 0)
64                                 break;
65                 }
66                 if (comp_algo < 0 && strcasecmp(s1, "default") == 0) {
67                         comp_algo = HAMMER2_COMP_LZ4;
68                         s1 = "lz4";
69                 }
70                 if (comp_algo < 0 && strcasecmp(s1, "disabled") == 0) {
71                         comp_algo = HAMMER2_COMP_AUTOZERO;
72                         s1 = "autozero";
73                 }
74                 if (comp_algo < 0) {
75                         fprintf(stderr, "Unknown compression type: %s\n", s1);
76                         ecode = 3;
77                 }
78         }
79         if (s2 == NULL) {
80                 comp_level = 0;
81         } else if (isdigit(s2[0])) {
82                 comp_level = strtol(s2, NULL, 0);
83         } else if (strcasecmp(s2, "default") == 0) {
84                 comp_level = 0;
85         } else {
86                 comp_level = 0;
87                 fprintf(stderr, "Unknown compression level: %s\n", s2);
88                 ecode = 3;
89         }
90
91         if (comp_level) {
92                 switch(comp_algo) {
93                 case HAMMER2_COMP_ZLIB:
94                         if (comp_level < 6 || comp_level > 9) {
95                                 fprintf(stderr,
96                                         "Unsupported comp_level %d for %s\n",
97                                         comp_level, s1);
98                                 ecode = 3;
99                         }
100                         break;
101                 default:
102                         fprintf(stderr,
103                                 "Unsupported comp_level %d for %s\n",
104                                 comp_level, s1);
105                         ecode = 3;
106                 }
107         }
108
109         if (ecode == 0) {
110                 while (*paths) {
111                         if (lstat(*paths, &st) == 0) {
112                                 res = cmd_setcomp_core(
113                                         HAMMER2_ENC_ALGO(comp_algo) |
114                                          HAMMER2_ENC_LEVEL(comp_level),
115                                         *paths,
116                                         &st);
117                                 if (res)
118                                         ecode = res;
119                         } else {
120                                 printf("%s: %s\n", *paths, strerror(errno));
121                                 ecode = 3;
122                         }
123                         ++paths;
124                 }
125         }
126         free (str);
127
128         return ecode;
129 }
130
131 static int
132 cmd_setcomp_core(uint8_t comp_algo, const char *path_str, struct stat *st)
133 {
134         hammer2_ioc_inode_t inode;
135         int fd;
136         int res;
137
138         fd = hammer2_ioctl_handle(path_str);
139         if (fd < 0) {
140                 res = 3;
141                 goto failed;
142         }
143         res = ioctl(fd, HAMMER2IOC_INODE_GET, &inode);
144         if (res < 0) {
145                 fprintf(stderr,
146                         "%s: HAMMER2IOC_INODE_GET: error %s\n",
147                         path_str, strerror(errno));
148                 res = 3;
149                 goto failed;
150         }
151         printf("%s\tcomp_algo=0x%02x\n", path_str, comp_algo);
152         inode.flags |= HAMMER2IOC_INODE_FLAG_COMP;
153         inode.ip_data.meta.comp_algo = comp_algo;
154         res = ioctl(fd, HAMMER2IOC_INODE_SET, &inode);
155         if (res < 0) {
156                 fprintf(stderr,
157                         "%s: HAMMER2IOC_INODE_SET: error %s\n",
158                         path_str, strerror(errno));
159                 res = 3;
160                 goto failed;
161         }
162         res = 0;
163
164         if (RecurseOpt && S_ISDIR(st->st_mode)) {
165                 DIR *dir;
166                 char *path;
167                 struct dirent *den;
168
169                 if ((dir = fdopendir(fd)) != NULL) {
170                         while ((den = readdir(dir)) != NULL) {
171                                 if (strcmp(den->d_name, ".") == 0 ||
172                                     strcmp(den->d_name, "..") == 0) {
173                                         continue;
174                                 }
175                                 asprintf(&path, "%s/%s", path_str, den->d_name);
176                                 if (lstat(path, st) == 0)
177                                         cmd_setcomp_core(comp_algo, path, st);
178                                 free(path);
179                         }
180                         closedir(dir);
181                 }
182         }
183 failed:
184         close(fd);
185         return res;
186 }
187
188 #if 0
189
190 int
191 cmd_setcomp_recursive(char* option_string, char* comp_string, char* file_string)
192 {
193         int ecode = 0;
194         int set_files;
195         int comp_method;
196
197         if (strcmp(option_string, "-r") == 0) {
198                 set_files = 0;
199         } else if (strcmp(option_string, "-rf") == 0) {
200                 set_files = 1;
201         } else {
202                 printf("setcomp: Unrecognized option.\n");
203                 exit(1);
204         }
205         if (strcmp(comp_string, "0") == 0) {
206                 printf("Will turn off compression on directory/file %s\n", file_string);
207                 comp_method = HAMMER2_COMP_NONE;
208         } else if (strcmp(comp_string, "1") == 0) {
209                 printf("Will set zero-checking compression on directory/file %s.\n", file_string);
210                 comp_method = HAMMER2_COMP_AUTOZERO;
211         } else if (strcmp(comp_string, "2") == 0) {
212                 printf("Will set LZ4 compression on directory/file %s.\n", file_string);
213                 comp_method = HAMMER2_COMP_LZ4;
214         } else if (strcmp(comp_string, "3") == 0) {
215                 printf("Will set ZLIB (slowest) compression on directory/file %s.\n", file_string);
216                 comp_method = HAMMER2_COMP_ZLIB;
217         }
218         else {
219                 printf("Unknown compression method.\n");
220                 return 1;
221         }
222         int fd = hammer2_ioctl_handle(file_string);
223         hammer2_ioc_inode_t inode;
224         int res = ioctl(fd, HAMMER2IOC_INODE_GET, &inode);
225         if (res < 0) {
226                 fprintf(stderr, "ERROR before setting the mode: %s\n", strerror(errno));
227                 return 3;
228         }
229         if (inode.ip_data.type != HAMMER2_OBJTYPE_DIRECTORY) {
230                 printf("setcomp: the specified object is not a directory, nothing changed.\n");
231                 return 1;
232         }
233         printf("Attention: recursive compression mode setting demanded, this may take a while...\n");
234         ecode = setcomp_recursive_call(file_string, comp_method, set_files);
235         inode.ip_data.comp_algo = comp_method;
236         res = ioctl(fd, HAMMER2IOC_INODE_SET, &inode);
237         if (res < 0) {
238                 if (errno != EINVAL) {
239                         fprintf(stderr, "ERROR after trying to set the mode: %s\n", strerror(errno));
240                         return 3;
241                 }
242         }
243         close(fd);
244         return ecode;
245 }
246
247 int
248 setcomp_recursive_call(char *directory, int comp_method, int set_files)
249 {
250         int ecode = 0;
251         DIR *dir;
252         if ((dir = opendir (directory)) == NULL) {
253         fprintf(stderr, "ERROR while trying to set the mode recursively: %s\n",
254                         strerror(errno));
255                 return 3;
256     }
257     struct dirent *dent;
258     int length;
259     length = strlen(directory);
260     char name[HAMMER2_INODE_MAXNAME];
261     strcpy(name, directory);
262     name[length] = '/';
263     ++length;
264     errno = 0;
265     dent = readdir(dir);
266     while (dent != NULL && ecode == 0) {
267                 if ((strcmp(dent->d_name, ".") != 0) &&
268                  (strcmp(dent->d_name, "..") != 0)) {
269                         strncpy(name + length, dent->d_name, HAMMER2_INODE_MAXNAME -
270                                 length);
271                         int fd = hammer2_ioctl_handle(name);
272                         hammer2_ioc_inode_t inode;
273                         int res = ioctl(fd, HAMMER2IOC_INODE_GET, &inode);
274                         if (res < 0) {
275                                 fprintf(stderr, "ERROR during recursion: %s\n",
276                                         strerror(errno));
277                                 return 3;
278                         }
279                         if (inode.ip_data.type == HAMMER2_OBJTYPE_DIRECTORY) {
280                                 ecode = setcomp_recursive_call(name, comp_method, set_files);
281                                 inode.ip_data.comp_algo = comp_method;
282                                 res = ioctl(fd, HAMMER2IOC_INODE_SET, &inode);
283                         }
284                         else {
285                                 if (set_files == 1 && inode.ip_data.type ==
286                                                 HAMMER2_OBJTYPE_REGFILE) {
287                                         inode.ip_data.comp_algo = comp_method;
288                                         res = ioctl(fd, HAMMER2IOC_INODE_SET, &inode);
289                                 }
290                         }
291                         if (res < 0) {
292                                 if (errno != EINVAL) {
293                                         fprintf(stderr, "ERROR during recursion after trying"
294                                                 "to set the mode: %s\n",
295                                                 strerror(errno));
296                                         return 3;
297                                 }
298                         }
299                         close(fd);
300                 }
301                 errno = 0; //we must set errno to 0 before readdir()
302                 dent = readdir(dir);
303         }
304         closedir(dir);
305         if (errno != 0) {
306                 fprintf(stderr, "ERROR during iteration: %s\n", strerror(errno));
307                 return 3;
308     }
309     return ecode;
310 }
311
312 #endif