xref: /netbsd-src/sbin/gpt/label.c (revision ccd9df534e375a4366c5b55f23782053c7a98d82)
1 /*-
2  * Copyright (c) 2005 Marcel Moolenaar
3  * All rights reserved.
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 the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #if HAVE_NBTOOL_CONFIG_H
28 #include "nbtool_config.h"
29 #endif
30 
31 #include <sys/cdefs.h>
32 #ifdef __FBSDID
33 __FBSDID("$FreeBSD: src/sbin/gpt/label.c,v 1.3 2006/10/04 18:20:25 marcel Exp $");
34 #endif
35 #ifdef __RCSID
36 __RCSID("$NetBSD: label.c,v 1.30 2019/06/21 02:14:59 jnemeth Exp $");
37 #endif
38 
39 #include <sys/types.h>
40 
41 #include <err.h>
42 #include <stddef.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47 
48 #include "map.h"
49 #include "gpt.h"
50 #include "gpt_private.h"
51 #include "gpt_uuid.h"
52 
53 static int cmd_label(gpt_t, int, char *[]);
54 
55 static const char *labelhelp[] = {
56 	"-a <-l label | -f file>",
57 	"[-b blocknr] [-i index] [-L label] [-s sectors] [-t uuid] "
58 	    "<-l label | -f file>",
59 };
60 
61 struct gpt_cmd c_label = {
62 	"label",
63 	cmd_label,
64 	labelhelp, __arraycount(labelhelp),
65 	GPT_SYNC,
66 };
67 
68 #define usage() gpt_usage(NULL, &c_label)
69 
70 static void
71 change(struct gpt_ent *ent, void *v, int backup)
72 {
73 	uint8_t *name = v;
74 	utf8_to_utf16(name, ent->ent_name, __arraycount(ent->ent_name));
75 }
76 
77 static int
78 name_from_file(gpt_t gpt, void *v)
79 {
80 	FILE *f;
81 	char *p;
82 	size_t maxlen = 1024;
83 	size_t len;
84 	const char *fn = optarg;
85 	char **name = v;
86 
87 	if (*name != NULL)
88 		return -1;
89 
90 	if (strcmp(fn, "-") != 0) {
91 		f = fopen(fn, "r");
92 		if (f == NULL) {
93 			gpt_warn(gpt, "Can't open `%s'", fn);
94 			return -1;
95 		}
96 	} else
97 		f = stdin;
98 
99 	if ((*name = malloc(maxlen)) == NULL) {
100 		gpt_warn(gpt, "Can't copy string");
101 		goto cleanup;
102 	}
103 	len = fread(*name, 1, maxlen - 1, f);
104 	if (ferror(f)) {
105 		gpt_warn(gpt, "Can't label from `%s'", fn);
106 		goto cleanup;
107 	}
108 	if (f != stdin)
109 		fclose(f);
110 	(*name)[len] = '\0';
111 	/* Only keep the first line, excluding the newline character. */
112 	p = strchr(*name, '\n');
113 	if (p != NULL)
114 		*p = '\0';
115 	return 0;
116 cleanup:
117 	free(*name);
118 	if (f != stdin)
119 		fclose(f);
120 	return -1;
121 }
122 
123 static int
124 cmd_label(gpt_t gpt, int argc, char *argv[])
125 {
126 	int ch;
127 	struct gpt_find find;
128 	char *name = NULL;
129 
130 	memset(&find, 0, sizeof(find));
131 	find.msg = "label changed";
132 
133 	/* Get the label options */
134 	while ((ch = getopt(argc, argv, GPT_FIND "f:l:")) != -1) {
135 		switch(ch) {
136 		case 'f':
137 			if (name_from_file(gpt, &name) == -1)
138 				goto usage;
139 			break;
140 		case 'l':
141 			if (gpt_name_get(gpt, &name) == -1)
142 				goto usage;
143 			break;
144 		default:
145 			if (gpt_add_find(gpt, &find, ch) == -1)
146 				goto usage;
147 			break;
148 		}
149 	}
150 
151 	if (name == NULL || argc != optind)
152 		goto usage;
153 
154 	return gpt_change_ent(gpt, &find, change, name);
155 usage:
156 	usage();
157 	free(name);
158 	return -1;
159 }
160