xref: /dflybsd-src/sbin/hammer2/cmd_setcomp.c (revision 450f08dbfd98cded95c51be4079ef10f5adb3241)
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 }
220