g_label_msdosfs.c revision 131476
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.
13131476Spjd *
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: head/sys/geom/label/g_label_msdosfs.c 131476 2004-07-02 19:40:36Z pjd $");
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_MSDOSFS_DIR	"msdosfs"
39131476Spjd
40131476Spjd#define	FAT12	"FAT12   "
41131476Spjd#define	FAT16	"FAT16   "
42131476Spjd#define	FAT32	"FAT32   "
43131476Spjd#define	VOLUME_LEN	11
44131476Spjd#define NO_NAME "NO NAME    "
45131476Spjd
46131476Spjd
47131476Spjdstatic void
48131476Spjdg_label_msdosfs_taste(struct g_consumer *cp, char *label, size_t size)
49131476Spjd{
50131476Spjd	struct g_provider *pp;
51131476Spjd	char *sector, *volume;
52131476Spjd	int i, error;
53131476Spjd
54131476Spjd	g_topology_assert_not();
55131476Spjd	pp = cp->provider;
56131476Spjd	label[0] = '\0';
57131476Spjd
58131476Spjd	sector = (char *)g_read_data(cp, 0, pp->sectorsize, &error);
59131476Spjd	if (sector == NULL || error != 0)
60131476Spjd		return;
61131476Spjd	if (strncmp(sector + 0x36, FAT12, strlen(FAT12)) == 0) {
62131476Spjd		G_LABEL_DEBUG(1, "MSDOS (FAT12) file system detected on %s.",
63131476Spjd		    pp->name);
64131476Spjd		volume = sector + 0x2b;
65131476Spjd	} else if (strncmp(sector + 0x36, FAT16, strlen(FAT16)) == 0) {
66131476Spjd		G_LABEL_DEBUG(1, "MSDOS (FAT16) file system detected on %s.",
67131476Spjd		    pp->name);
68131476Spjd		volume = sector + 0x2b;
69131476Spjd	} else if (strncmp(sector + 0x52, FAT32, strlen(FAT32)) == 0) {
70131476Spjd		G_LABEL_DEBUG(1, "MSDOS (FAT32) file system detected on %s.",
71131476Spjd		    pp->name);
72131476Spjd		volume = sector + 0x47;
73131476Spjd	} else {
74131476Spjd		g_free(sector);
75131476Spjd		return;
76131476Spjd	}
77131476Spjd	if (strncmp(volume, NO_NAME, VOLUME_LEN) == 0) {
78131476Spjd		g_free(sector);
79131476Spjd		return;
80131476Spjd	}
81131476Spjd	if (volume[0] == '\0') {
82131476Spjd		g_free(sector);
83131476Spjd		return;
84131476Spjd	}
85131476Spjd	bzero(label, size);
86131476Spjd	strlcpy(label, volume, MIN(size, VOLUME_LEN));
87131476Spjd	g_free(sector);
88131476Spjd	for (i = size - 1; i > 0; i--) {
89131476Spjd		if (label[i] == '\0')
90131476Spjd			continue;
91131476Spjd		else if (label[i] == ' ')
92131476Spjd			label[i] = '\0';
93131476Spjd		else
94131476Spjd			break;
95131476Spjd	}
96131476Spjd}
97131476Spjd
98131476Spjdconst struct g_label_desc g_label_msdosfs = {
99131476Spjd	.ld_taste = g_label_msdosfs_taste,
100131476Spjd	.ld_dir = G_LABEL_MSDOSFS_DIR
101131476Spjd};
102