]>
Commit | Line | Data |
---|---|---|
2bd0ea18 | 1 | /* |
cc08d43e | 2 | * Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. |
2bd0ea18 NS |
3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | |
5 | * under the terms of version 2 of the GNU General Public License as | |
6 | * published by the Free Software Foundation. | |
7 | * | |
8 | * This program is distributed in the hope that it would be useful, but | |
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
11 | * | |
12 | * Further, this software is distributed without any warranty that it is | |
13 | * free of the rightful claim of any third person regarding infringement | |
14 | * or the like. Any license provided herein, whether implied or | |
15 | * otherwise, applies only to this software file. Patent licenses, if | |
16 | * any, provided herein do not apply to combinations of this program with | |
17 | * other software, or any other product whatsoever. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License along | |
20 | * with this program; if not, write the Free Software Foundation, Inc., 59 | |
21 | * Temple Place - Suite 330, Boston MA 02111-1307, USA. | |
22 | * | |
23 | * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, | |
24 | * Mountain View, CA 94043, or: | |
25 | * | |
26 | * http://www.sgi.com | |
27 | * | |
28 | * For further information regarding this notice, see: | |
29 | * | |
30 | * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ | |
31 | */ | |
32 | ||
33 | #include <libxfs.h> | |
34 | #include "command.h" | |
35 | #include "data.h" | |
36 | #include "type.h" | |
37 | #include "faddr.h" | |
38 | #include "fprint.h" | |
39 | #include "field.h" | |
40 | #include "io.h" | |
41 | #include "uuid.h" | |
42 | #include "bit.h" | |
43 | #include "output.h" | |
44 | #include "mount.h" | |
45 | ||
46 | static int uuid_f(int argc, char **argv); | |
47 | static void uuid_help(void); | |
48 | static int label_f(int argc, char **argv); | |
49 | static void label_help(void); | |
50 | ||
51 | static const cmdinfo_t uuid_cmd = | |
52 | { "uuid", NULL, uuid_f, 0, 1, 1, "[uuid]", | |
53 | "write/print FS uuid", uuid_help }; | |
54 | static const cmdinfo_t label_cmd = | |
55 | { "label", NULL, label_f, 0, 1, 1, "[label]", | |
56 | "write/print FS label", label_help }; | |
57 | static int warned; | |
58 | ||
59 | static void | |
60 | uuid_help(void) | |
61 | { | |
62 | dbprintf( | |
63 | "\n" | |
64 | " write/print FS uuid\n" | |
65 | "\n" | |
66 | " Example:\n" | |
67 | "\n" | |
68 | " 'uuid' - print UUID\n" | |
69 | " 'uuid 01234567-0123-0123-0123-0123456789ab' - write UUID\n" | |
70 | " 'uuid generate' - generate and write\n" | |
71 | " 'uuid rewrite' - copy UUID from SB 0\n" | |
2bd0ea18 NS |
72 | "\n" |
73 | "The print function checks the UUID in each SB and will warn if the UUIDs\n" | |
74 | "differ between AGs (the log is not checked). The write commands will\n" | |
75 | "set the uuid in all AGs to either a specified value, a newly generated\n" | |
7242da3f DM |
76 | "value or the value found in the first superblock (SB 0) respectively.\n" |
77 | "As a side effect of writing the UUID, the log is cleared (which is fine\n" | |
78 | "on a CLEANLY unmounted FS).\n" | |
2bd0ea18 NS |
79 | "\n" |
80 | ); | |
81 | } | |
82 | ||
83 | static void | |
84 | label_help(void) | |
85 | { | |
86 | dbprintf( | |
87 | "\n" | |
88 | " write/print FS label\n" | |
89 | "\n" | |
90 | " Example:\n" | |
91 | "\n" | |
92 | " 'label' - print label\n" | |
93 | " 'label 123456789012' - write label\n" | |
94 | " 'label --' - write an empty label\n" | |
95 | "\n" | |
96 | "The print function checks the label in each SB and will warn if the labels\n" | |
97 | "differ between AGs. The write commands will set the label in all AGs to the\n" | |
98 | "specified value. The maximum length of a label is 12 characters - use of a\n" | |
99 | "longer label will result in truncation and a warning will be issued.\n" | |
100 | "\n" | |
101 | ); | |
102 | } | |
103 | ||
104 | static int | |
105 | get_sb(xfs_agnumber_t agno, xfs_sb_t *sb) | |
106 | { | |
107 | push_cur(); | |
108 | set_cur(&typtab[TYP_SB], XFS_AG_DADDR(mp, agno, XFS_SB_DADDR), 1, | |
109 | DB_RING_IGN, NULL); | |
110 | ||
111 | if (!iocur_top->data) { | |
112 | dbprintf("can't read superblock for AG %u\n", agno); | |
113 | pop_cur(); | |
114 | return 0; | |
115 | } | |
116 | ||
117 | libxfs_xlate_sb(iocur_top->data, sb, 1, ARCH_CONVERT, XFS_SB_ALL_BITS); | |
118 | ||
119 | if (sb->sb_magicnum != XFS_SB_MAGIC) { | |
120 | dbprintf("bad sb magic # %#x in AG %u\n", | |
121 | sb->sb_magicnum, agno); | |
122 | return 0; | |
123 | } | |
124 | if (!XFS_SB_GOOD_VERSION(sb)) { | |
125 | dbprintf("bad sb version # %#x in AG %u\n", | |
126 | sb->sb_versionnum, agno); | |
127 | return 0; | |
128 | } | |
129 | if (agno == 0 && sb->sb_inprogress != 0) { | |
130 | dbprintf("mkfs not completed successfully\n"); | |
131 | return 0; | |
132 | } | |
133 | return 1; | |
134 | } | |
135 | ||
136 | static uuid_t * | |
137 | do_uuid(xfs_agnumber_t agno, uuid_t *uuid) | |
138 | { | |
139 | xfs_sb_t tsb; | |
140 | static uuid_t uu; | |
141 | ||
142 | if (!get_sb(agno, &tsb)) | |
143 | return NULL; | |
144 | ||
145 | if (!uuid) { /* get uuid */ | |
146 | memcpy(&uu, &tsb.sb_uuid, sizeof(uuid_t)); | |
147 | pop_cur(); | |
148 | return &uu; | |
149 | } | |
150 | /* set uuid */ | |
151 | memcpy(&tsb.sb_uuid, uuid, sizeof(uuid_t)); | |
152 | libxfs_xlate_sb(iocur_top->data, &tsb, -1, ARCH_CONVERT, XFS_SB_UUID); | |
153 | write_cur(); | |
154 | return uuid; | |
155 | } | |
156 | ||
157 | static char * | |
158 | do_label(xfs_agnumber_t agno, char *label) | |
159 | { | |
160 | size_t len; | |
161 | xfs_sb_t tsb; | |
162 | static char lbl[sizeof(tsb.sb_fname) + 1]; | |
163 | ||
164 | if (!get_sb(agno, &tsb)) | |
165 | return NULL; | |
166 | ||
167 | memset(&lbl[0], 0, sizeof(lbl)); | |
168 | ||
169 | if (!label) { /* get label */ | |
170 | pop_cur(); | |
171 | memcpy(&lbl[0], &tsb.sb_fname, sizeof(tsb.sb_fname)); | |
172 | return &lbl[0]; | |
173 | } | |
174 | /* set label */ | |
175 | if ((len = strlen(label)) > sizeof(tsb.sb_fname)) { | |
176 | if (!warned++) | |
7242da3f DM |
177 | dbprintf("warning: truncating label from %lld to %lld " |
178 | "characters\n", | |
179 | (long long)len, (long long)sizeof(tsb.sb_fname)); | |
2bd0ea18 NS |
180 | len = sizeof(tsb.sb_fname); |
181 | } | |
182 | if ( len == 2 && | |
183 | (strcmp(label, "\"\"") == 0 || | |
184 | strcmp(label, "''") == 0 || | |
185 | strcmp(label, "--") == 0) ) | |
186 | label[0] = label[1] = '\0'; | |
187 | memset(&tsb.sb_fname, 0, sizeof(tsb.sb_fname)); | |
188 | memcpy(&tsb.sb_fname, label, len); | |
189 | memcpy(&lbl[0], &tsb.sb_fname, sizeof(tsb.sb_fname)); | |
190 | libxfs_xlate_sb(iocur_top->data, &tsb, -1, ARCH_CONVERT, XFS_SB_FNAME); | |
191 | write_cur(); | |
192 | return &lbl[0]; | |
193 | } | |
194 | ||
195 | static int | |
196 | uuid_f( | |
197 | int argc, | |
198 | char **argv) | |
199 | { | |
200 | char bp[40]; | |
201 | xfs_agnumber_t agno; | |
202 | uuid_t uu; | |
203 | uuid_t *uup=NULL; | |
204 | ||
205 | if (argc != 1 && argc != 2) { | |
206 | dbprintf("invalid parameters\n"); | |
207 | return 0; | |
208 | } | |
209 | ||
210 | if (argc==2) { | |
211 | /* write uuid */ | |
212 | ||
213 | if (flag_readonly || !flag_expert_mode) { | |
214 | dbprintf("%s not started in read-write expert mode, writing disabled\n", | |
215 | progname); | |
216 | return 0; | |
217 | } | |
218 | ||
219 | if (!strcasecmp(argv[1], "generate")) { | |
220 | uuid_generate(uu); | |
7242da3f | 221 | } else if (!strcasecmp(argv[1], "nil")) { |
2bd0ea18 NS |
222 | uuid_clear(uu); |
223 | } else if (!strcasecmp(argv[1], "rewrite")) { | |
224 | uup=do_uuid(0, NULL); | |
225 | if (!uup) { | |
226 | dbprintf("failed to read UUID from AG 0\n"); | |
227 | return 0; | |
228 | } | |
229 | memcpy(&uu, *uup, sizeof(uuid_t)); | |
230 | uuid_unparse(uu, bp); | |
231 | dbprintf("old uuid = %s\n", bp); | |
232 | } else { | |
233 | if (uuid_parse(argv[1], uu)) { | |
234 | dbprintf("invalid uuid\n"); | |
235 | return 0; | |
236 | } | |
237 | } | |
238 | ||
239 | if (mp->m_sb.sb_logstart) { | |
240 | if (xfsargs.logdev) { | |
241 | dbprintf("external log specified for FS with internal log - aborting \n"); | |
242 | return 0; | |
243 | } | |
244 | } else { | |
245 | if (!xfsargs.logdev) { | |
246 | dbprintf("no external log specified for FS with external log - aborting\n"); | |
247 | return 0; | |
248 | } | |
249 | } | |
250 | ||
251 | dbprintf("clearing log and setting uuid\n"); | |
252 | ||
253 | /* clear log (setting uuid) */ | |
254 | ||
255 | if (libxfs_log_clear( | |
256 | (mp->m_sb.sb_logstart)?xfsargs.ddev:xfsargs.logdev, | |
257 | XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart), | |
258 | XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks), | |
259 | &uu, | |
260 | XLOG_FMT)) { | |
261 | dbprintf("error clearing log\n"); | |
262 | return 0; | |
263 | } | |
264 | ||
265 | ||
266 | dbprintf("writing all SBs\n"); | |
267 | ||
268 | for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) | |
269 | if (!do_uuid(agno, &uu)) { | |
270 | dbprintf("failed to set uuid in AG %d\n", agno); | |
271 | break; | |
272 | } | |
273 | ||
274 | uuid_unparse(uu, bp); | |
275 | dbprintf("new uuid = %s\n", bp); | |
276 | ||
277 | return 0; | |
278 | ||
279 | } else { | |
280 | /* get (check) uuid */ | |
281 | ||
282 | for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { | |
283 | uup=do_uuid(agno, NULL); | |
284 | if (!uup) { | |
285 | dbprintf("failed to read UUID from AG %d\n", agno); | |
286 | return 0; | |
287 | } | |
288 | if (agno) { | |
289 | if (memcmp(&uu, uup, sizeof(uuid_t))) { | |
290 | dbprintf("warning: uuid copies differ\n"); | |
291 | break; | |
292 | } | |
293 | } else { | |
294 | memcpy(uu, uup, sizeof(uuid_t)); | |
295 | } | |
296 | } | |
297 | if (mp->m_sb.sb_logstart) { | |
298 | if (xfsargs.logdev) | |
299 | dbprintf("warning: external log specified for FS with internal log\n"); | |
300 | } else { | |
301 | if (!xfsargs.logdev) { | |
302 | dbprintf("warning: no external log specified for FS with external log\n"); | |
303 | } | |
304 | } | |
305 | ||
306 | uuid_unparse(uu, bp); | |
307 | dbprintf("uuid = %s\n", bp); | |
308 | } | |
309 | ||
310 | return 0; | |
311 | } | |
312 | ||
313 | static int | |
314 | label_f( | |
315 | int argc, | |
316 | char **argv) | |
317 | { | |
318 | char *p = NULL; | |
319 | xfs_sb_t sb; | |
320 | xfs_agnumber_t ag; | |
321 | ||
322 | if (argc != 1 && argc != 2) { | |
323 | dbprintf("invalid parameters\n"); | |
324 | return 0; | |
325 | } | |
326 | ||
327 | if (argc==2) { /* write label */ | |
328 | if (flag_readonly || !flag_expert_mode) { | |
329 | dbprintf("%s not started in read-write expert mode, " | |
330 | "writing disabled\n", progname); | |
331 | return 0; | |
332 | } | |
333 | ||
334 | dbprintf("writing all SBs\n"); | |
335 | for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) | |
336 | if ((p = do_label(ag, argv[1])) == NULL) { | |
337 | dbprintf("failed to set label in AG %d\n", ag); | |
338 | break; | |
339 | } | |
340 | dbprintf("new label = \"%s\"\n", p); | |
341 | } else { /* print label */ | |
342 | for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) { | |
343 | p = do_label(ag, NULL); | |
344 | if (!p) { | |
345 | dbprintf("failed to read label in AG %d\n", ag); | |
346 | return 0; | |
347 | } | |
348 | if (!ag) | |
349 | memcpy(&sb.sb_fname, p, sizeof(sb.sb_fname)); | |
350 | else if (memcmp(&sb.sb_fname, p, sizeof(sb.sb_fname))) | |
7242da3f | 351 | dbprintf("warning: label in AG %d differs\n", ag); |
2bd0ea18 NS |
352 | } |
353 | dbprintf("label = \"%s\"\n", p); | |
354 | } | |
355 | return 0; | |
356 | } | |
357 | ||
358 | void | |
359 | uuid_init(void) | |
360 | { | |
361 | warned = 0; | |
362 | add_command(&label_cmd); | |
363 | add_command(&uuid_cmd); | |
364 | } |