hammer2 - Add directives for setting the check mode
[dragonfly.git] / sbin / hammer2 / cmd_setcheck.c
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_ISCSI32;
61                         check_str = "crc32";
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.ip_data.check_algo = check_algo;
117         res = ioctl(fd, HAMMER2IOC_INODE_SET, &inode);
118         if (res < 0) {
119                 fprintf(stderr,
120                         "%s: HAMMER2IOC_INODE_SET: error %s\n",
121                         path_str, strerror(errno));
122                 res = 3;
123                 goto failed;
124         }
125         res = 0;
126
127         if (RecurseOpt && S_ISDIR(st->st_mode)) {
128                 DIR *dir;
129                 char *path;
130                 struct dirent *den;
131
132                 if ((dir = fdopendir(fd)) != NULL) {
133                         while ((den = readdir(dir)) != NULL) {
134                                 if (strcmp(den->d_name, ".") == 0 ||
135                                     strcmp(den->d_name, "..") == 0) {
136                                         continue;
137                                 }
138                                 asprintf(&path, "%s/%s", path_str, den->d_name);
139                                 if (lstat(path, st) == 0)
140                                         cmd_setcheck_core(check_algo, path, st);
141                                 free(path);
142                         }
143                         closedir(dir);
144                 }
145         }
146 failed:
147         close(fd);
148         return res;
149 }