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