xref: /dflybsd-src/sbin/hammer/cmd_config.c (revision 9930da22423478e7af8fc6461fc059d567ef9543)
183f2a3aaSMatthew Dillon /*
283f2a3aaSMatthew Dillon  * Copyright (c) 2009 The DragonFly Project.  All rights reserved.
383f2a3aaSMatthew Dillon  *
483f2a3aaSMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
583f2a3aaSMatthew Dillon  * by Matthew Dillon <dillon@backplane.com>
683f2a3aaSMatthew Dillon  *
783f2a3aaSMatthew Dillon  * Redistribution and use in source and binary forms, with or without
883f2a3aaSMatthew Dillon  * modification, are permitted provided that the following conditions
983f2a3aaSMatthew Dillon  * are met:
1083f2a3aaSMatthew Dillon  *
1183f2a3aaSMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
1283f2a3aaSMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
1383f2a3aaSMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
1483f2a3aaSMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
1583f2a3aaSMatthew Dillon  *    the documentation and/or other materials provided with the
1683f2a3aaSMatthew Dillon  *    distribution.
1783f2a3aaSMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
1883f2a3aaSMatthew Dillon  *    contributors may be used to endorse or promote products derived
1983f2a3aaSMatthew Dillon  *    from this software without specific, prior written permission.
2083f2a3aaSMatthew Dillon  *
2183f2a3aaSMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2283f2a3aaSMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2383f2a3aaSMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2483f2a3aaSMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
2583f2a3aaSMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2683f2a3aaSMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
2783f2a3aaSMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2883f2a3aaSMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2983f2a3aaSMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
3083f2a3aaSMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
3183f2a3aaSMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3283f2a3aaSMatthew Dillon  * SUCH DAMAGE.
3383f2a3aaSMatthew Dillon  */
3483f2a3aaSMatthew Dillon 
35b45803e3STomohiro Kusumi #include "hammer.h"
36b45803e3STomohiro Kusumi 
3783f2a3aaSMatthew Dillon static void config_get(const char *dirpath, struct hammer_ioc_config *config);
3883f2a3aaSMatthew Dillon static void config_set(const char *dirpath, struct hammer_ioc_config *config);
3983f2a3aaSMatthew Dillon static void config_remove_path(void);
4083f2a3aaSMatthew Dillon 
41c6a47f25STomohiro Kusumi static char *ConfigPath;
4283f2a3aaSMatthew Dillon 
4383f2a3aaSMatthew Dillon /*
4483f2a3aaSMatthew Dillon  * hammer config [<fs> [configfile]]
4583f2a3aaSMatthew Dillon  *
4683f2a3aaSMatthew Dillon  * Prints out the hammer cleanup configuration for the specified HAMMER
4783f2a3aaSMatthew Dillon  * filesystem(s) or the current filesystem.
4883f2a3aaSMatthew Dillon  */
4983f2a3aaSMatthew Dillon void
hammer_cmd_config(char ** av,int ac)5083f2a3aaSMatthew Dillon hammer_cmd_config(char **av, int ac)
5183f2a3aaSMatthew Dillon {
5283f2a3aaSMatthew Dillon 	struct hammer_ioc_config config;
5383f2a3aaSMatthew Dillon 	char *dirpath;
5483f2a3aaSMatthew Dillon 	ssize_t n;
5583f2a3aaSMatthew Dillon 	int fd;
5683f2a3aaSMatthew Dillon 
5783f2a3aaSMatthew Dillon 	bzero(&config, sizeof(config));
5883f2a3aaSMatthew Dillon 	if (ac == 0) {
5983f2a3aaSMatthew Dillon 		config_get(".", &config);
60f254e677STomohiro Kusumi 		if (config.head.error == 0) {
6183f2a3aaSMatthew Dillon 			printf("%s", config.config.text);
62f254e677STomohiro Kusumi 		} else {
6383f2a3aaSMatthew Dillon 			errx(2, "hammer config: no configuration found");
64f254e677STomohiro Kusumi 			/* not reached */
65f254e677STomohiro Kusumi 		}
6683f2a3aaSMatthew Dillon 		return;
6783f2a3aaSMatthew Dillon 	}
6883f2a3aaSMatthew Dillon 	dirpath = av[0];
6983f2a3aaSMatthew Dillon 	if (ac == 1) {
7083f2a3aaSMatthew Dillon 		config_get(dirpath, &config);
71f254e677STomohiro Kusumi 		if (config.head.error == 0) {
7283f2a3aaSMatthew Dillon 			printf("%s", config.config.text);
73f254e677STomohiro Kusumi 		} else {
7483f2a3aaSMatthew Dillon 			errx(2, "hammer config: no configuration found");
75f254e677STomohiro Kusumi 			/* not reached */
76f254e677STomohiro Kusumi 		}
7783f2a3aaSMatthew Dillon 		return;
7883f2a3aaSMatthew Dillon 	}
7983f2a3aaSMatthew Dillon 	config_get(dirpath, &config);	/* ignore errors */
8083f2a3aaSMatthew Dillon 	config.head.error = 0;
8183f2a3aaSMatthew Dillon 
8283f2a3aaSMatthew Dillon 	fd = open(av[1], O_RDONLY);
83f254e677STomohiro Kusumi 	if (fd < 0) {
84154eb1f4SStathis Kamperis 		err(2, "hammer config: %s", av[1]);
85f254e677STomohiro Kusumi 		/* not reached */
86f254e677STomohiro Kusumi 	}
8783f2a3aaSMatthew Dillon 	n = read(fd, config.config.text, sizeof(config.config.text) - 1);
88f254e677STomohiro Kusumi 	if (n == sizeof(config.config.text) - 1) {
8913a23276SMatthew Dillon 		err(2, "hammer config: config file too big, limit %zu bytes",
9083f2a3aaSMatthew Dillon 		    sizeof(config.config.text) - 1);
91f254e677STomohiro Kusumi 		/* not reached */
92f254e677STomohiro Kusumi 	}
9383f2a3aaSMatthew Dillon 	bzero(config.config.text + n, sizeof(config.config.text) - n);
9483f2a3aaSMatthew Dillon 	config_set(dirpath, &config);
9583f2a3aaSMatthew Dillon 	close(fd);
9683f2a3aaSMatthew Dillon }
9783f2a3aaSMatthew Dillon 
9883f2a3aaSMatthew Dillon /*
9983f2a3aaSMatthew Dillon  * hammer viconfig [<fs>]
10083f2a3aaSMatthew Dillon  */
10183f2a3aaSMatthew Dillon void
hammer_cmd_viconfig(char ** av,int ac)10283f2a3aaSMatthew Dillon hammer_cmd_viconfig(char **av, int ac)
10383f2a3aaSMatthew Dillon {
10483f2a3aaSMatthew Dillon 	struct hammer_ioc_config config;
10583f2a3aaSMatthew Dillon 	struct timeval times[2];
10683f2a3aaSMatthew Dillon 	const char *dirpath;
10783f2a3aaSMatthew Dillon 	struct stat st;
10893c6d6c7SAntonio Huete Jimenez 	char *runcmd, *editor, *tmp;
10983f2a3aaSMatthew Dillon 	char path[32];
11083f2a3aaSMatthew Dillon 	ssize_t n;
11183f2a3aaSMatthew Dillon 	int fd;
11283f2a3aaSMatthew Dillon 
113f254e677STomohiro Kusumi 	if (ac > 1) {
11483f2a3aaSMatthew Dillon 		errx(1, "hammer viconfig: 0 or 1 argument (<fs>) only");
115f254e677STomohiro Kusumi 		/* not reached */
116f254e677STomohiro Kusumi 	}
11783f2a3aaSMatthew Dillon 	if (ac == 0)
11883f2a3aaSMatthew Dillon 		dirpath = ".";
11983f2a3aaSMatthew Dillon 	else
12083f2a3aaSMatthew Dillon 		dirpath = av[0];
12183f2a3aaSMatthew Dillon 	config_get(dirpath, &config);
12283f2a3aaSMatthew Dillon 	if (config.head.error == ENOENT) {
12383f2a3aaSMatthew Dillon 		snprintf(config.config.text, sizeof(config.config.text),
12483f2a3aaSMatthew Dillon 			"%s",
12583f2a3aaSMatthew Dillon 			"# No configuration present, here are some defaults\n"
12683f2a3aaSMatthew Dillon 			"# you can uncomment.  Also remove these instructions\n"
12783f2a3aaSMatthew Dillon 			"#\n"
12883f2a3aaSMatthew Dillon                         "#snapshots 1d 60d\n"
12983f2a3aaSMatthew Dillon                         "#prune     1d 5m\n"
13083f2a3aaSMatthew Dillon                         "#rebalance 1d 5m\n"
131bb29b5d8SMatthew Dillon                         "#dedup     1d 5m\n"
13283f2a3aaSMatthew Dillon                         "#reblock   1d 5m\n"
13342fd37d3SThomas Nikolajsen                         "#recopy    30d 10m\n");
13483f2a3aaSMatthew Dillon 		config.head.error = 0;
13583f2a3aaSMatthew Dillon 	}
136f254e677STomohiro Kusumi 	if (config.head.error) {
13783f2a3aaSMatthew Dillon 		errx(2, "hammer viconfig: read config failed error: %s",
13883f2a3aaSMatthew Dillon 			strerror(config.head.error));
139f254e677STomohiro Kusumi 		/* not reached */
140f254e677STomohiro Kusumi 	}
14183f2a3aaSMatthew Dillon 
14283f2a3aaSMatthew Dillon 	/*
14383f2a3aaSMatthew Dillon 	 * Edit a temporary file and write back if it was modified.
14483f2a3aaSMatthew Dillon 	 * Adjust the mtime back one second so a quick edit is not
14583f2a3aaSMatthew Dillon 	 * improperly detected as not having been modified.
14683f2a3aaSMatthew Dillon 	 */
14783f2a3aaSMatthew Dillon 	snprintf(path, sizeof(path), "/tmp/configXXXXXXXXXX");
14883f2a3aaSMatthew Dillon 	mkstemp(path);
14983f2a3aaSMatthew Dillon 	ConfigPath = path;
15083f2a3aaSMatthew Dillon 	atexit(config_remove_path);
15183f2a3aaSMatthew Dillon 
15283f2a3aaSMatthew Dillon 	fd = open(path, O_RDWR|O_CREAT|O_TRUNC, 0600);
153052fd72bSTomohiro Kusumi 	if (fd < 0) {
15483f2a3aaSMatthew Dillon 		err(2, "hammer viconfig: creating temporary file %s", path);
155052fd72bSTomohiro Kusumi 		/* not reached */
156052fd72bSTomohiro Kusumi 	}
15783f2a3aaSMatthew Dillon 	write(fd, config.config.text, strlen(config.config.text));
158052fd72bSTomohiro Kusumi 	if (fstat(fd, &st) < 0) {
15983f2a3aaSMatthew Dillon 		err(2, "hammer viconfig");
160052fd72bSTomohiro Kusumi 		/* not reached */
161052fd72bSTomohiro Kusumi 	}
16283f2a3aaSMatthew Dillon 	times[0].tv_sec = st.st_mtime - 1;
16383f2a3aaSMatthew Dillon 	times[0].tv_usec = 0;
16483f2a3aaSMatthew Dillon 	times[1] = times[0];
16583f2a3aaSMatthew Dillon 	close(fd);
16683f2a3aaSMatthew Dillon 	utimes(path, times);
16783f2a3aaSMatthew Dillon 
16893c6d6c7SAntonio Huete Jimenez 	if ((tmp = getenv("EDITOR")) != NULL ||
169*9930da22STomohiro Kusumi 	    (tmp = getenv("VISUAL")) != NULL) {
17093c6d6c7SAntonio Huete Jimenez 		editor = strdup(tmp);
171*9930da22STomohiro Kusumi 	} else {
17293c6d6c7SAntonio Huete Jimenez 		editor = strdup("vi");
173*9930da22STomohiro Kusumi 	}
17493c6d6c7SAntonio Huete Jimenez 
17593c6d6c7SAntonio Huete Jimenez 	asprintf(&runcmd, "%s %s", editor, path);
17683f2a3aaSMatthew Dillon 	system(runcmd);
17783f2a3aaSMatthew Dillon 
178052fd72bSTomohiro Kusumi 	if (stat(path, &st) < 0) {
17983f2a3aaSMatthew Dillon 		err(2, "hammer viconfig: unable to stat file after vi");
180052fd72bSTomohiro Kusumi 		/* not reached */
181052fd72bSTomohiro Kusumi 	}
18283f2a3aaSMatthew Dillon 	if (times[0].tv_sec == st.st_mtime) {
18383f2a3aaSMatthew Dillon 		printf("hammer viconfig: no changes were made\n");
18483f2a3aaSMatthew Dillon 		remove(path);
18583f2a3aaSMatthew Dillon 		return;
18683f2a3aaSMatthew Dillon 	}
18783f2a3aaSMatthew Dillon 	fd = open(path, O_RDONLY);
188052fd72bSTomohiro Kusumi 	if (fd < 0) {
18983f2a3aaSMatthew Dillon 		err(2, "hammer viconfig: unable to read %s", path);
190052fd72bSTomohiro Kusumi 		/* not reached */
191052fd72bSTomohiro Kusumi 	}
19283f2a3aaSMatthew Dillon 	remove(path);
19383f2a3aaSMatthew Dillon 	n = read(fd, config.config.text, sizeof(config.config.text) - 1);
194052fd72bSTomohiro Kusumi 	if (n < 0) {
19583f2a3aaSMatthew Dillon 		err(2, "hammer viconfig: unable to read %s", path);
196052fd72bSTomohiro Kusumi 		/* not reached */
197052fd72bSTomohiro Kusumi 	}
198f254e677STomohiro Kusumi 	if (n == sizeof(config.config.text) - 1) {
19913a23276SMatthew Dillon 		err(2, "hammer config: config file too big, limit %zu bytes",
20083f2a3aaSMatthew Dillon 		    sizeof(config.config.text) - 1);
201f254e677STomohiro Kusumi 		/* not reached */
202f254e677STomohiro Kusumi 	}
20383f2a3aaSMatthew Dillon 	bzero(config.config.text + n, sizeof(config.config.text) - n);
20483f2a3aaSMatthew Dillon 	config_set(dirpath, &config);
20593c6d6c7SAntonio Huete Jimenez 	free(editor);
20693c6d6c7SAntonio Huete Jimenez 	free(runcmd);
20783f2a3aaSMatthew Dillon }
20883f2a3aaSMatthew Dillon 
209005a4da7STomohiro Kusumi static
210005a4da7STomohiro Kusumi void
config_get(const char * dirpath,struct hammer_ioc_config * config)21183f2a3aaSMatthew Dillon config_get(const char *dirpath, struct hammer_ioc_config *config)
21283f2a3aaSMatthew Dillon {
21383f2a3aaSMatthew Dillon 	struct hammer_ioc_version version;
21483f2a3aaSMatthew Dillon 	int fd;
21583f2a3aaSMatthew Dillon 
21683f2a3aaSMatthew Dillon 	bzero(&version, sizeof(version));
217052fd72bSTomohiro Kusumi 	if ((fd = open(dirpath, O_RDONLY)) < 0) {
21883f2a3aaSMatthew Dillon 		err(2, "hammer config: unable to open directory %s", dirpath);
219052fd72bSTomohiro Kusumi 		/* not reached */
220052fd72bSTomohiro Kusumi 	}
221052fd72bSTomohiro Kusumi 	if (ioctl(fd, HAMMERIOC_GET_VERSION, &version) < 0) {
22283f2a3aaSMatthew Dillon 		errx(2, "hammer config: not a HAMMER filesystem!");
223052fd72bSTomohiro Kusumi 		/* not reached */
224052fd72bSTomohiro Kusumi 	}
2254c09d9c4SMatthew Dillon 	HammerVersion = version.cur_version;
226052fd72bSTomohiro Kusumi 	if (ioctl(fd, HAMMERIOC_GET_CONFIG, config) < 0) {
22783f2a3aaSMatthew Dillon 		errx(2, "hammer config: config_get");
228052fd72bSTomohiro Kusumi 		/* not reached */
229052fd72bSTomohiro Kusumi 	}
23083f2a3aaSMatthew Dillon 	close(fd);
23183f2a3aaSMatthew Dillon }
23283f2a3aaSMatthew Dillon 
233005a4da7STomohiro Kusumi static
234005a4da7STomohiro Kusumi void
config_set(const char * dirpath,struct hammer_ioc_config * config)23583f2a3aaSMatthew Dillon config_set(const char *dirpath, struct hammer_ioc_config *config)
23683f2a3aaSMatthew Dillon {
23783f2a3aaSMatthew Dillon 	struct hammer_ioc_version version;
23883f2a3aaSMatthew Dillon 	int fd;
23983f2a3aaSMatthew Dillon 
24083f2a3aaSMatthew Dillon 	bzero(&version, sizeof(version));
241052fd72bSTomohiro Kusumi 	if ((fd = open(dirpath, O_RDONLY)) < 0) {
24283f2a3aaSMatthew Dillon 		errx(2, "hammer config: unable to open directory %s", dirpath);
243052fd72bSTomohiro Kusumi 		/* not reached */
244052fd72bSTomohiro Kusumi 	}
245052fd72bSTomohiro Kusumi 	if (ioctl(fd, HAMMERIOC_GET_VERSION, &version) < 0) {
24683f2a3aaSMatthew Dillon 		errx(2, "hammer config: not a HAMMER filesystem!");
247052fd72bSTomohiro Kusumi 		/* not reached */
248052fd72bSTomohiro Kusumi 	}
2494c09d9c4SMatthew Dillon 	HammerVersion = version.cur_version;
250052fd72bSTomohiro Kusumi 	if (ioctl(fd, HAMMERIOC_SET_CONFIG, config) < 0) {
25193c6d6c7SAntonio Huete Jimenez 		err(2, "hammer config");
252052fd72bSTomohiro Kusumi 		/* not reached */
253052fd72bSTomohiro Kusumi 	}
25483f2a3aaSMatthew Dillon 	close(fd);
25583f2a3aaSMatthew Dillon }
25683f2a3aaSMatthew Dillon 
257005a4da7STomohiro Kusumi static
258005a4da7STomohiro Kusumi void
config_remove_path(void)25983f2a3aaSMatthew Dillon config_remove_path(void)
26083f2a3aaSMatthew Dillon {
26183f2a3aaSMatthew Dillon 	remove(ConfigPath);
26283f2a3aaSMatthew Dillon }
263