1131476Spjd/*-
2131476Spjd * Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3131476Spjd * All rights reserved.
4131476Spjd *
5131476Spjd * Redistribution and use in source and binary forms, with or without
6131476Spjd * modification, are permitted provided that the following conditions
7131476Spjd * are met:
8131476Spjd * 1. Redistributions of source code must retain the above copyright
9131476Spjd *    notice, this list of conditions and the following disclaimer.
10131476Spjd * 2. Redistributions in binary form must reproduce the above copyright
11131476Spjd *    notice, this list of conditions and the following disclaimer in the
12131476Spjd *    documentation and/or other materials provided with the distribution.
13155174Spjd *
14131476Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15131476Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16131476Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17131476Spjd * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18131476Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19131476Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20131476Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21131476Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22131476Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23131476Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24131476Spjd * SUCH DAMAGE.
25131476Spjd */
26131476Spjd
27131476Spjd#include <sys/cdefs.h>
28131476Spjd__FBSDID("$FreeBSD$");
29131476Spjd
30131476Spjd#include <sys/param.h>
31131476Spjd#include <sys/systm.h>
32131476Spjd#include <sys/kernel.h>
33131476Spjd#include <sys/malloc.h>
34131476Spjd
35131476Spjd#include <geom/geom.h>
36131476Spjd#include <geom/label/g_label.h>
37131476Spjd
38131476Spjd#define G_LABEL_ISO9660_DIR	"iso9660"
39131476Spjd
40131476Spjd#define	ISO9660_MAGIC	"\x01" "CD001" "\x01\x00"
41149495Spjd#define	ISO9660_OFFSET	0x8000
42131476Spjd#define	VOLUME_LEN	32
43131476Spjd
44131476Spjd
45131476Spjdstatic void
46131476Spjdg_label_iso9660_taste(struct g_consumer *cp, char *label, size_t size)
47131476Spjd{
48131476Spjd	struct g_provider *pp;
49131476Spjd	char *sector, *volume;
50131476Spjd
51131476Spjd	g_topology_assert_not();
52131476Spjd	pp = cp->provider;
53131476Spjd	label[0] = '\0';
54131476Spjd
55149495Spjd	if ((ISO9660_OFFSET % pp->sectorsize) != 0)
56149495Spjd		return;
57149495Spjd	sector = (char *)g_read_data(cp, ISO9660_OFFSET, pp->sectorsize,
58152971Ssobomax	    NULL);
59152967Ssobomax	if (sector == NULL)
60131476Spjd		return;
61131476Spjd	if (bcmp(sector, ISO9660_MAGIC, sizeof(ISO9660_MAGIC) - 1) != 0) {
62131476Spjd		g_free(sector);
63131476Spjd		return;
64131476Spjd	}
65131476Spjd	G_LABEL_DEBUG(1, "ISO9660 file system detected on %s.", pp->name);
66131476Spjd	volume = sector + 0x28;
67131476Spjd	bzero(label, size);
68131476Spjd	strlcpy(label, volume, MIN(size, VOLUME_LEN));
69131476Spjd	g_free(sector);
70286193Strasz	g_label_rtrim(label, size);
71131476Spjd}
72131476Spjd
73199875Straszstruct g_label_desc g_label_iso9660 = {
74131476Spjd	.ld_taste = g_label_iso9660_taste,
75199875Strasz	.ld_dir = G_LABEL_ISO9660_DIR,
76199875Strasz	.ld_enabled = 1
77131476Spjd};
78199875Strasz
79199875StraszG_LABEL_INIT(iso9660, g_label_iso9660, "Create device nodes for ISO9660 volume names");
80