4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 * Label a file system volume.
41 #include <sys/fcntl.h>
42 #include <sys/param.h>
43 #include <sys/types.h>
44 #include <sys/mntent.h>
46 #include <sys/fs/udf_volume.h>
49 static uint8_t buf
[MAXBSIZE
];
52 static int8_t lvinfo1_buf
[BUF_LEN
];
53 static int8_t lvinfo2_buf
[BUF_LEN
];
54 static int8_t lvinfo3_buf
[BUF_LEN
];
55 static int8_t fsname
[BUF_LEN
];
56 static int8_t volname
[BUF_LEN
];
57 static int32_t fsname_len
;
59 #define SET_LVINFO1 0x01
60 #define SET_LVINFO2 0x02
61 #define SET_LVINFO3 0x04
62 #define SET_FSNAME 0x08
63 #define SET_VOLNAME 0x10
65 typedef unsigned short unicode_t
;
67 #define FSNAME_STR_LEN (8 + 2)
68 #define VOLNAME_STR_LEN 32
69 #define INFO_STR_LEN 36
72 static void label(ud_handle_t
, uint32_t);
73 static void print_info(struct vds
*, char *, ud_handle_t
);
74 static void label_vds(struct vds
*, uint32_t, ud_handle_t
);
75 static int32_t convert_string(int8_t *, int8_t *, int32_t, int32_t, int8_t *);
76 static int32_t ud_convert2unicode(int8_t *, int8_t *, int32_t);
79 int8_t *labelit_subopts
[] = {
90 main(int32_t argc
, char *argv
[])
95 int8_t *options
= NULL
;
97 uint32_t set_flags
= 0;
100 (void) setlocale(LC_ALL
, "");
102 #if !defined(TEXT_DOMAIN)
103 #define TEXT_DOMAIN "SYS_TEST"
106 (void) textdomain(TEXT_DOMAIN
);
109 while ((opt
= getopt(argc
, argv
, "F:o:")) != EOF
) {
112 if (strcmp(optarg
, "udfs") != 0) {
119 * UDFS specific options
122 while (*options
!= '\0') {
123 switch (getsubopt(&options
, labelit_subopts
,
126 set_flags
|= SET_LVINFO1
;
127 (void) convert_string(value
,
128 lvinfo1_buf
, BUF_LEN
,
130 gettext("udfs labelit: lvinfo1 should be less than "
131 "36 bytes after converting to compressed unicode "
135 set_flags
|= SET_LVINFO2
;
136 (void) convert_string(value
,
137 lvinfo2_buf
, BUF_LEN
,
139 gettext("udfs labelit: lvinfo2 should be less than "
140 "36 bytes after converting to compressed unicode "
144 set_flags
|= SET_LVINFO3
;
145 (void) convert_string(value
,
146 lvinfo3_buf
, BUF_LEN
,
148 gettext("udfs labelit: lvinfo3 should be less than "
149 "36 bytes after converting to compressed unicode "
153 (void) fprintf(stderr
,
154 gettext("udfs labelit: Unknown suboption %s\n"), value
);
166 if ((argc
- optind
) == 3) {
169 * There are restrictions on the
170 * length of the names
171 * fsname is 8 characters
172 * volume name is 32 characters
173 * The extra byte is for compression id
175 fsname_len
= convert_string(argv
[optind
+ 1],
176 fsname
, BUF_LEN
, FSNAME_STR_LEN
,
177 gettext("udfs labelit: fsname can not be longer than 8 characters\n"));
179 (void) convert_string(argv
[optind
+ 2],
180 volname
, BUF_LEN
, VOLNAME_STR_LEN
,
181 gettext("udfs labelit: volname can not be longer "
182 "than 32 bytes after converting to "
183 "compressed unicode dstring\n"));
184 set_flags
|= SET_FSNAME
| SET_VOLNAME
;
186 if ((argc
- optind
) != 1) {
191 if (ud_init(-1, &udh
) != 0) {
192 (void) fprintf(stderr
,
193 gettext("udfs labelit: cannot initialize ud_lib\n"));
198 * Open special device
200 if (set_flags
== 0) {
205 if (ud_open_dev(udh
, argv
[optind
], flags
) != 0) {
206 (void) fprintf(stderr
,
207 gettext("udfs labelit: cannot open <%s> errorno <%d>\n"),
208 argv
[optind
], errno
);
212 if ((ret
= ud_fill_udfs_info(udh
)) != 0) {
216 if ((udh
->udfs
.flags
& VALID_UDFS
) == 0) {
221 label(udh
, set_flags
);
233 (void) fprintf(stderr
, gettext(
234 "udfs usage: labelit [-F udfs] [generic options] "
235 "[ -o specific_options ] special [fsname volume]\n"));
236 (void) fprintf(stderr
, gettext(
237 " -o : specific_options : [lvinfo1=string],"
238 "[lvinfo2=string],[lvinfo3=string]\n"));
239 (void) fprintf(stderr
,
240 gettext("NOTE that all -o suboptions: must"
241 " be separated only by commas.\n"));
246 label(ud_handle_t udh
, uint32_t set_flags
)
248 if (set_flags
== 0) {
249 if (udh
->udfs
.flags
& VALID_MVDS
) {
250 print_info(&udh
->udfs
.mvds
, "mvds", udh
);
252 if (udh
->udfs
.flags
& VALID_RVDS
) {
253 print_info(&udh
->udfs
.rvds
, "rvds", udh
);
258 if (udh
->udfs
.flags
& VALID_MVDS
) {
259 label_vds(&udh
->udfs
.mvds
, set_flags
, udh
);
261 if (udh
->udfs
.flags
& VALID_RVDS
) {
262 label_vds(&udh
->udfs
.rvds
, set_flags
, udh
);
264 if (((set_flags
& (SET_FSNAME
| SET_VOLNAME
)) ==
265 (SET_FSNAME
| SET_VOLNAME
)) &&
266 (udh
->udfs
.fsd_len
!= 0)) {
267 struct file_set_desc
*fsd
;
269 off
= udh
->udfs
.fsd_loc
* udh
->udfs
.lbsize
;
270 if (ud_read_dev(udh
, off
, buf
,
271 udh
->udfs
.fsd_len
) != 0) {
276 fsd
= (struct file_set_desc
*)buf
;
278 set_dstring(fsd
->fsd_lvid
,
279 volname
, sizeof (fsd
->fsd_lvid
));
280 set_dstring(fsd
->fsd_fsi
,
281 volname
, sizeof (fsd
->fsd_fsi
));
283 ud_make_tag(udh
, &fsd
->fsd_tag
, UD_FILE_SET_DESC
,
284 SWAP_32(fsd
->fsd_tag
.tag_loc
),
285 SWAP_16(fsd
->fsd_tag
.tag_crc_len
));
287 (void) ud_write_dev(udh
, off
, buf
, udh
->udfs
.fsd_len
);
293 print_info(struct vds
*v
, char *name
, ud_handle_t udh
)
295 uint8_t outbuf
[BUF_LEN
];
297 if (v
->pvd_len
!= 0) {
298 off
= v
->pvd_loc
* udh
->udfs
.lbsize
;
299 if (ud_read_dev(udh
, off
, buf
,
300 sizeof (struct pri_vol_desc
)) == 0) {
302 struct pri_vol_desc
*pvd
;
305 pvd
= (struct pri_vol_desc
*)buf
;
307 bzero(outbuf
, BUF_LEN
);
308 (void) ud_convert2local(
309 (int8_t *)pvd
->pvd_vsi
,
310 (int8_t *)outbuf
, strlen(pvd
->pvd_vsi
));
311 (void) fprintf(stdout
,
312 gettext("fsname in %s : %s\n"),
315 bzero(outbuf
, BUF_LEN
);
316 pvd
->pvd_vol_id
[31] = '\0';
317 (void) ud_convert2local(
318 (int8_t *)pvd
->pvd_vol_id
,
320 strlen(pvd
->pvd_vol_id
));
321 (void) fprintf(stdout
,
322 gettext("volume label in %s : %s\n"),
327 if (v
->iud_len
!= 0) {
328 off
= v
->iud_loc
* udh
->udfs
.lbsize
;
329 if (ud_read_dev(udh
, off
, buf
,
330 sizeof (struct iuvd_desc
)) == 0) {
332 struct iuvd_desc
*iud
;
335 iud
= (struct iuvd_desc
*)buf
;
336 bzero(outbuf
, BUF_LEN
);
337 iud
->iuvd_ifo1
[35] = '\0';
338 (void) ud_convert2local(
339 (int8_t *)iud
->iuvd_ifo1
,
341 strlen(iud
->iuvd_ifo1
));
342 (void) fprintf(stdout
,
343 gettext("LVInfo1 in %s : %s\n"),
346 bzero(outbuf
, BUF_LEN
);
347 iud
->iuvd_ifo2
[35] = '\0';
348 (void) ud_convert2local(
349 (int8_t *)iud
->iuvd_ifo2
,
351 strlen(iud
->iuvd_ifo2
));
352 (void) fprintf(stdout
,
353 gettext("LVInfo2 in %s : %s\n"),
356 bzero(outbuf
, BUF_LEN
);
357 iud
->iuvd_ifo3
[35] = '\0';
358 (void) ud_convert2local(
359 (int8_t *)iud
->iuvd_ifo3
,
361 strlen(iud
->iuvd_ifo3
));
362 (void) fprintf(stdout
,
363 gettext("LVInfo3 in %s : %s\n"),
371 label_vds(struct vds
*v
, uint32_t set_flags
, ud_handle_t udh
)
374 if (((set_flags
& (SET_FSNAME
| SET_VOLNAME
)) ==
375 (SET_FSNAME
| SET_VOLNAME
)) &&
378 off
= v
->pvd_loc
* udh
->udfs
.lbsize
;
379 if (ud_read_dev(udh
, off
, buf
,
380 sizeof (struct pri_vol_desc
)) == 0) {
382 struct pri_vol_desc
*pvd
;
385 pvd
= (struct pri_vol_desc
*)buf
;
386 bzero((int8_t *)&pvd
->pvd_vsi
[9], 119);
387 (void) strncpy((int8_t *)&pvd
->pvd_vsi
[9],
388 &fsname
[1], fsname_len
- 1);
390 set_dstring(pvd
->pvd_vol_id
,
391 volname
, sizeof (pvd
->pvd_vol_id
));
393 ud_make_tag(udh
, &pvd
->pvd_tag
,
394 SWAP_16(pvd
->pvd_tag
.tag_id
),
395 SWAP_32(pvd
->pvd_tag
.tag_loc
),
396 SWAP_16(pvd
->pvd_tag
.tag_crc_len
));
398 (void) ud_write_dev(udh
, off
, buf
,
399 sizeof (struct pri_vol_desc
));
403 if (set_flags
&& v
->iud_len
) {
405 off
= v
->iud_loc
* udh
->udfs
.lbsize
;
406 if (ud_read_dev(udh
, off
, buf
,
407 sizeof (struct iuvd_desc
)) == 0) {
409 struct iuvd_desc
*iuvd
;
412 iuvd
= (struct iuvd_desc
*)buf
;
414 if ((set_flags
& SET_VOLNAME
) == SET_VOLNAME
) {
415 set_dstring(iuvd
->iuvd_lvi
,
416 volname
, sizeof (iuvd
->iuvd_lvi
));
418 if ((set_flags
& SET_LVINFO1
) == SET_LVINFO1
) {
419 set_dstring(iuvd
->iuvd_ifo1
,
420 lvinfo1_buf
, sizeof (iuvd
->iuvd_ifo1
));
422 if ((set_flags
& SET_LVINFO2
) == SET_LVINFO2
) {
423 set_dstring(iuvd
->iuvd_ifo2
,
424 lvinfo2_buf
, sizeof (iuvd
->iuvd_ifo2
));
426 if ((set_flags
& SET_LVINFO3
) == SET_LVINFO3
) {
427 set_dstring(iuvd
->iuvd_ifo3
,
428 lvinfo3_buf
, sizeof (iuvd
->iuvd_ifo3
));
431 ud_make_tag(udh
, &iuvd
->iuvd_tag
,
432 SWAP_16(iuvd
->iuvd_tag
.tag_id
),
433 SWAP_32(iuvd
->iuvd_tag
.tag_loc
),
434 SWAP_16(iuvd
->iuvd_tag
.tag_crc_len
));
436 (void) ud_write_dev(udh
, off
, buf
,
437 sizeof (struct iuvd_desc
));
441 if (((set_flags
& (SET_FSNAME
| SET_VOLNAME
)) ==
442 (SET_FSNAME
| SET_VOLNAME
)) &&
445 off
= v
->lvd_loc
* udh
->udfs
.lbsize
;
446 if (ud_read_dev(udh
, off
, buf
,
447 sizeof (struct log_vol_desc
)) == 0) {
449 struct log_vol_desc
*lvd
;
452 lvd
= (struct log_vol_desc
*)buf
;
453 set_dstring(lvd
->lvd_lvid
,
454 volname
, sizeof (lvd
->lvd_lvid
));
456 ud_make_tag(udh
, &lvd
->lvd_tag
,
457 SWAP_16(lvd
->lvd_tag
.tag_id
),
458 SWAP_32(lvd
->lvd_tag
.tag_loc
),
459 SWAP_16(lvd
->lvd_tag
.tag_crc_len
));
461 (void) ud_write_dev(udh
, off
, buf
,
462 sizeof (struct log_vol_desc
));
469 convert_string(int8_t *value
, int8_t *out_buf
, int32_t out_len
,
470 int32_t len
, int8_t *error_string
)
472 int32_t out_length
= 0;
474 out_length
= ud_convert2unicode(value
, out_buf
, out_len
);
475 if (out_length
> len
- 1) {
476 (void) fprintf(stderr
, "%s", error_string
);
484 ud_convert2unicode(int8_t *mb
, int8_t *comp
, int32_t out_len
)
492 len
= mbstowcs(buf4c
, mb
, 127);
495 for (i
= 0; i
< len
; i
++) {
496 if (buf4c
[i
] & 0xFFFFFF00) {
504 for (i
= 0; i
< len
&& i
< out_len
; i
++) {
506 comp
[j
] = (buf4c
[i
] & 0xFF00) >> 8;
508 comp
[j
++] = buf4c
[i
] & 0xFF;