2 * Copyright (c) 2013 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@dragonflybsd.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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
37 static int cmd_setcomp_core(uint8_t comp_algo
, const char *path_str
,
41 cmd_setcomp(const char *comp_str
, char **paths
)
43 static const char *comps
[] = HAMMER2_COMP_STRINGS
;
53 str
= strdup(comp_str
);
54 s1
= strtok(str
, ":");
55 s2
= s1
? strtok(NULL
, ":") : NULL
;
59 comp_algo
= strtol(s1
, NULL
, 0);
61 comp_algo
= HAMMER2_COMP_STRINGS_COUNT
;
62 while (--comp_algo
>= 0) {
63 if (strcasecmp(s1
, comps
[comp_algo
]) == 0)
66 if (comp_algo
< 0 && strcasecmp(s1
, "default") == 0) {
67 comp_algo
= HAMMER2_COMP_LZ4
;
70 if (comp_algo
< 0 && strcasecmp(s1
, "disabled") == 0) {
71 comp_algo
= HAMMER2_COMP_AUTOZERO
;
75 fprintf(stderr
, "Unknown compression type: %s\n", s1
);
81 } else if (isdigit(s2
[0])) {
82 comp_level
= strtol(s2
, NULL
, 0);
83 } else if (strcasecmp(s2
, "default") == 0) {
87 fprintf(stderr
, "Unknown compression level: %s\n", s2
);
93 case HAMMER2_COMP_ZLIB
:
94 if (comp_level
< 6 || comp_level
> 9) {
96 "Unsupported comp_level %d for %s\n",
103 "Unsupported comp_level %d for %s\n",
111 if (lstat(*paths
, &st
) == 0) {
112 res
= cmd_setcomp_core(
113 HAMMER2_ENC_ALGO(comp_algo
) |
114 HAMMER2_ENC_LEVEL(comp_level
),
120 printf("%s: %s\n", *paths
, strerror(errno
));
132 cmd_setcomp_core(uint8_t comp_algo
, const char *path_str
, struct stat
*st
)
134 hammer2_ioc_inode_t inode
;
138 fd
= hammer2_ioctl_handle(path_str
);
143 res
= ioctl(fd
, HAMMER2IOC_INODE_GET
, &inode
);
146 "%s: HAMMER2IOC_INODE_GET: error %s\n",
147 path_str
, strerror(errno
));
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
);
157 "%s: HAMMER2IOC_INODE_SET: error %s\n",
158 path_str
, strerror(errno
));
164 if (RecurseOpt
&& S_ISDIR(st
->st_mode
)) {
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) {
175 asprintf(&path
, "%s/%s", path_str
, den
->d_name
);
176 if (lstat(path
, st
) == 0)
177 cmd_setcomp_core(comp_algo
, path
, st
);
191 cmd_setcomp_recursive(char* option_string
, char* comp_string
, char* file_string
)
197 if (strcmp(option_string
, "-r") == 0) {
199 } else if (strcmp(option_string
, "-rf") == 0) {
202 printf("setcomp: Unrecognized option.\n");
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
;
219 printf("Unknown compression method.\n");
222 int fd
= hammer2_ioctl_handle(file_string
);
223 hammer2_ioc_inode_t inode
;
224 int res
= ioctl(fd
, HAMMER2IOC_INODE_GET
, &inode
);
226 fprintf(stderr
, "ERROR before setting the mode: %s\n", strerror(errno
));
229 if (inode
.ip_data
.type
!= HAMMER2_OBJTYPE_DIRECTORY
) {
230 printf("setcomp: the specified object is not a directory, nothing changed.\n");
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
);
238 if (errno
!= EINVAL
) {
239 fprintf(stderr
, "ERROR after trying to set the mode: %s\n", strerror(errno
));
248 setcomp_recursive_call(char *directory
, int comp_method
, int set_files
)
252 if ((dir
= opendir (directory
)) == NULL
) {
253 fprintf(stderr
, "ERROR while trying to set the mode recursively: %s\n",
259 length
= strlen(directory
);
260 char name
[HAMMER2_INODE_MAXNAME
];
261 strcpy(name
, directory
);
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
-
271 int fd
= hammer2_ioctl_handle(name
);
272 hammer2_ioc_inode_t inode
;
273 int res
= ioctl(fd
, HAMMER2IOC_INODE_GET
, &inode
);
275 fprintf(stderr
, "ERROR during recursion: %s\n",
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
);
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
);
292 if (errno
!= EINVAL
) {
293 fprintf(stderr
, "ERROR during recursion after trying"
294 "to set the mode: %s\n",
301 errno
= 0; //we must set errno to 0 before readdir()
306 fprintf(stderr
, "ERROR during iteration: %s\n", strerror(errno
));