xref: /dragonfly/sbin/hammer2/cmd_setcheck.c (revision 37de577a)
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_setcheck_core(uint8_t check_algo, const char *path_str,
38 			    struct stat *st);
39 
40 int
41 cmd_setcheck(const char *check_str, char **paths)
42 {
43 	static const char *checks[] = HAMMER2_CHECK_STRINGS;
44 	struct stat st;
45 	int check_algo;
46 	int ecode;
47 	int res;
48 
49 	ecode = 0;
50 
51 	if (isdigit(check_str[0])) {
52 		check_algo = strtol(check_str, NULL, 0);
53 	} else {
54 		check_algo = HAMMER2_CHECK_STRINGS_COUNT;
55 		while (--check_algo >= 0) {
56 			if (strcasecmp(check_str, checks[check_algo]) == 0)
57 				break;
58 		}
59 		if (check_algo < 0 && strcasecmp(check_str, "default") == 0) {
60 			check_algo = HAMMER2_CHECK_XXHASH64;
61 			check_str = "xxhash64";
62 		}
63 		if (check_algo < 0 && strcasecmp(check_str, "disabled") == 0) {
64 			check_algo = HAMMER2_CHECK_DISABLED;
65 			check_str = "disabled";
66 		}
67 		if (check_algo < 0) {
68 			fprintf(stderr,
69 				"Unknown check code type: %s\n",
70 				check_str);
71 			ecode = 3;
72 		}
73 	}
74 
75 	if (ecode == 0) {
76 		while (*paths) {
77 			if (lstat(*paths, &st) == 0) {
78 				res = cmd_setcheck_core(
79 					HAMMER2_ENC_ALGO(check_algo),
80 				        *paths,
81 					&st);
82 				if (res)
83 					ecode = res;
84 			} else {
85 				printf("%s: %s\n", *paths, strerror(errno));
86 				ecode = 3;
87 			}
88 			++paths;
89 		}
90 	}
91 
92 	return ecode;
93 }
94 
95 static int
96 cmd_setcheck_core(uint8_t check_algo, const char *path_str, struct stat *st)
97 {
98 	hammer2_ioc_inode_t inode;
99 	int fd;
100 	int res;
101 
102 	fd = hammer2_ioctl_handle(path_str);
103 	if (fd < 0) {
104 		res = 3;
105 		goto failed;
106 	}
107 	res = ioctl(fd, HAMMER2IOC_INODE_GET, &inode);
108 	if (res < 0) {
109 		fprintf(stderr,
110 			"%s: HAMMER2IOC_INODE_GET: error %s\n",
111 			path_str, strerror(errno));
112 		res = 3;
113 		goto failed;
114 	}
115 	printf("%s\tcheck_algo=0x%02x\n", path_str, check_algo);
116 	inode.flags |= HAMMER2IOC_INODE_FLAG_CHECK;
117 	inode.ip_data.meta.check_algo = check_algo;
118 	res = ioctl(fd, HAMMER2IOC_INODE_SET, &inode);
119 	if (res < 0) {
120 		fprintf(stderr,
121 			"%s: HAMMER2IOC_INODE_SET: error %s\n",
122 			path_str, strerror(errno));
123 		res = 3;
124 		goto failed;
125 	}
126 	res = 0;
127 
128 	if (RecurseOpt && S_ISDIR(st->st_mode)) {
129 		DIR *dir;
130 		char *path;
131 		struct dirent *den;
132 
133 		if ((dir = fdopendir(fd)) != NULL) {
134 			while ((den = readdir(dir)) != NULL) {
135 				if (strcmp(den->d_name, ".") == 0 ||
136 				    strcmp(den->d_name, "..") == 0) {
137 					continue;
138 				}
139 				asprintf(&path, "%s/%s", path_str, den->d_name);
140 				if (lstat(path, st) == 0)
141 					cmd_setcheck_core(check_algo, path, st);
142 				free(path);
143 			}
144 			closedir(dir);
145 		}
146 	}
147 failed:
148 	close(fd);
149 	return res;
150 }
151