Merge branch 'vendor/XZ'
[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.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 }