2 * Copyright (c) 2013 The DragonFly Project. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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
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.
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
35 static int cmd_setcomp_core(uint8_t comp_algo, const char *path_str,
39 cmd_setcomp(const char *comp_str, char **paths)
41 static const char *comps[] = HAMMER2_COMP_STRINGS;
51 str = strdup(comp_str);
52 s1 = strtok(str, ":");
53 s2 = s1 ? strtok(NULL, ":") : NULL;
57 comp_algo = strtol(s1, NULL, 0);
59 comp_algo = HAMMER2_COMP_STRINGS_COUNT;
60 while (--comp_algo >= 0) {
61 if (strcasecmp(s1, comps[comp_algo]) == 0)
64 if (comp_algo < 0 && strcasecmp(s1, "default") == 0) {
65 comp_algo = HAMMER2_COMP_LZ4;
68 if (comp_algo < 0 && strcasecmp(s1, "disabled") == 0) {
69 comp_algo = HAMMER2_COMP_AUTOZERO;
73 fprintf(stderr, "Unknown compression type: %s\n", s1);
79 } else if (isdigit(s2[0])) {
80 comp_level = strtol(s2, NULL, 0);
81 } else if (strcasecmp(s2, "default") == 0) {
85 fprintf(stderr, "Unknown compression level: %s\n", s2);
91 case HAMMER2_COMP_ZLIB:
92 if (comp_level < 6 || comp_level > 9) {
94 "Unsupported comp_level %d for %s\n",
101 "Unsupported comp_level %d for %s\n",
109 if (lstat(*paths, &st) == 0) {
110 res = cmd_setcomp_core(
111 HAMMER2_ENC_COMP(comp_algo) |
112 HAMMER2_ENC_LEVEL(comp_level),
118 printf("%s: %s\n", *paths, strerror(errno));
130 cmd_setcomp_core(uint8_t comp_algo, const char *path_str, struct stat *st)
132 hammer2_ioc_inode_t inode;
136 fd = hammer2_ioctl_handle(path_str);
141 res = ioctl(fd, HAMMER2IOC_INODE_GET, &inode);
144 "%s: HAMMER2IOC_INODE_GET: error %s\n",
145 path_str, strerror(errno));
149 printf("%s\tcomp_algo=0x%02x\n", path_str, comp_algo);
150 inode.ip_data.comp_algo = comp_algo;
151 res = ioctl(fd, HAMMER2IOC_INODE_SET, &inode);
154 "%s: HAMMER2IOC_INODE_SET: error %s\n",
155 path_str, strerror(errno));
161 if (RecurseOpt && S_ISDIR(st->st_mode)) {
166 if ((dir = fdopendir(fd)) != NULL) {
167 while ((den = readdir(dir)) != NULL) {
168 if (strcmp(den->d_name, ".") == 0 ||
169 strcmp(den->d_name, "..") == 0) {
172 asprintf(&path, "%s/%s", path_str, den->d_name);
173 if (lstat(path, st) == 0)
174 cmd_setcomp_core(comp_algo, path, st);
188 cmd_setcomp_recursive(char* option_string, char* comp_string, char* file_string)
194 if (strcmp(option_string, "-r") == 0) {
196 } else if (strcmp(option_string, "-rf") == 0) {
199 printf("setcomp: Unrecognized option.\n");
202 if (strcmp(comp_string, "0") == 0) {
203 printf("Will turn off compression on directory/file %s\n", file_string);
204 comp_method = HAMMER2_COMP_NONE;
205 } else if (strcmp(comp_string, "1") == 0) {
206 printf("Will set zero-checking compression on directory/file %s.\n", file_string);
207 comp_method = HAMMER2_COMP_AUTOZERO;
208 } else if (strcmp(comp_string, "2") == 0) {
209 printf("Will set LZ4 compression on directory/file %s.\n", file_string);
210 comp_method = HAMMER2_COMP_LZ4;
211 } else if (strcmp(comp_string, "3") == 0) {
212 printf("Will set ZLIB (slowest) compression on directory/file %s.\n", file_string);
213 comp_method = HAMMER2_COMP_ZLIB;
216 printf("Unknown compression method.\n");
219 int fd = hammer2_ioctl_handle(file_string);
220 hammer2_ioc_inode_t inode;
221 int res = ioctl(fd, HAMMER2IOC_INODE_GET, &inode);
223 fprintf(stderr, "ERROR before setting the mode: %s\n", strerror(errno));
226 if (inode.ip_data.type != HAMMER2_OBJTYPE_DIRECTORY) {
227 printf("setcomp: the specified object is not a directory, nothing changed.\n");
230 printf("Attention: recursive compression mode setting demanded, this may take a while...\n");
231 ecode = setcomp_recursive_call(file_string, comp_method, set_files);
232 inode.ip_data.comp_algo = comp_method;
233 res = ioctl(fd, HAMMER2IOC_INODE_SET, &inode);
235 if (errno != EINVAL) {
236 fprintf(stderr, "ERROR after trying to set the mode: %s\n", strerror(errno));
245 setcomp_recursive_call(char *directory, int comp_method, int set_files)
249 if ((dir = opendir (directory)) == NULL) {
250 fprintf(stderr, "ERROR while trying to set the mode recursively: %s\n",
256 lenght = strlen(directory);
257 char name[HAMMER2_INODE_MAXNAME];
258 strcpy(name, directory);
263 while (dent != NULL && ecode == 0) {
264 if ((strcmp(dent->d_name, ".") != 0) &&
265 (strcmp(dent->d_name, "..") != 0)) {
266 strncpy(name + lenght, dent->d_name, HAMMER2_INODE_MAXNAME -
268 int fd = hammer2_ioctl_handle(name);
269 hammer2_ioc_inode_t inode;
270 int res = ioctl(fd, HAMMER2IOC_INODE_GET, &inode);
272 fprintf(stderr, "ERROR during recursion: %s\n",
276 if (inode.ip_data.type == HAMMER2_OBJTYPE_DIRECTORY) {
277 ecode = setcomp_recursive_call(name, comp_method, set_files);
278 inode.ip_data.comp_algo = comp_method;
279 res = ioctl(fd, HAMMER2IOC_INODE_SET, &inode);
282 if (set_files == 1 && inode.ip_data.type ==
283 HAMMER2_OBJTYPE_REGFILE) {
284 inode.ip_data.comp_algo = comp_method;
285 res = ioctl(fd, HAMMER2IOC_INODE_SET, &inode);
289 if (errno != EINVAL) {
290 fprintf(stderr, "ERROR during recursion after trying"
291 "to set the mode: %s\n",
298 errno = 0; //we must set errno to 0 before readdir()
303 fprintf(stderr, "ERROR during iteration: %s\n", strerror(errno));