disk.c revision 8153
1/*
2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@login.dknet.dk> wrote this file.  As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
8 *
9 * $Id$
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <unistd.h>
16#include <fcntl.h>
17#include <string.h>
18#include <err.h>
19#include <sys/types.h>
20#include <sys/ioctl.h>
21#include <sys/disklabel.h>
22#include <sys/diskslice.h>
23#include <sys/queue.h>
24#include "libdisk.h"
25
26#define DOSPTYP_EXTENDED        5
27#define DOSPTYP_ONTRACK         84
28
29struct disk *
30Open_Disk(char *name)
31{
32	return Int_Open_Disk(name,0);
33}
34
35struct disk *
36Int_Open_Disk(char *name, u_long size)
37{
38	int i,fd;
39	struct diskslices ds;
40	char device[64];
41	struct disk *d;
42
43	strcpy(device,"/dev/r");
44	strcat(device,name);
45
46	fd = open(device,O_RDONLY);
47	if (fd < 0) {
48		warn("open(%s) failed",device);
49		return 0;
50	}
51	i = ioctl(fd,DIOCGSLICEINFO,&ds);
52	if (i < 0) {
53		warn("DIOCSLICEINFO(%s) failed",device);
54		close(fd);
55		return 0;
56	}
57
58	d = (struct disk *)malloc(sizeof *d);
59	if(!d) err(1,"malloc failed");
60
61	memset(d,0,sizeof *d);
62
63	d->name = strdup(name);
64
65	if (!size)
66		size = ds.dss_slices[WHOLE_DISK_SLICE].ds_size;
67
68	Add_Chunk(d, 0, size, name,whole,0,0);
69
70	for(i=2;i<ds.dss_nslices;i++) {
71		char sname[20];
72		chunk_e ce;
73		u_long flags=0;
74		int subtype=0;
75		if (! ds.dss_slices[i].ds_size)
76			continue;
77		sprintf(sname,"%ss%d",name,i-1);
78		switch (ds.dss_slices[i].ds_type) {
79			case 0xa5:
80				ce = freebsd;
81				break;
82			case 0x1:
83			case 0x6:
84				ce = fat;
85				break;
86			case DOSPTYP_EXTENDED:
87				ce = extended;
88				break;
89			default:
90				ce = foo;
91				subtype = -ds.dss_slices[i].ds_type;
92				break;
93		}
94		flags |= CHUNK_ALIGN;
95		Add_Chunk(d,ds.dss_slices[i].ds_offset,
96			ds.dss_slices[i].ds_size, sname,ce,subtype,flags);
97		if (ds.dss_slices[i].ds_type == 0xa5) {
98			struct disklabel *dl;
99			int j;
100
101			dl = read_disklabel(fd,
102				ds.dss_slices[i].ds_offset + LABELSECTOR);
103			if(dl) {
104				for(j=0; j < dl->d_npartitions; j++) {
105					char pname[20];
106					sprintf(pname,"%s%c",sname,j+'a');
107					if (j == 2)
108						continue;
109					if (!dl->d_partitions[j].p_size)
110						continue;
111					Add_Chunk(d,
112						dl->d_partitions[j].p_offset,
113						dl->d_partitions[j].p_size,
114						pname,part,0,0);
115				}
116			}
117			free(dl);
118		}
119	}
120	close(fd);
121	return d;
122}
123
124void
125Debug_Disk(struct disk *d)
126{
127	printf("Debug_Disk(%s)",d->name);
128	printf("  flags=%lx",d->flags);
129	printf("  real_geom=%lu/%lu/%lu",d->real_cyl,d->real_hd,d->real_sect);
130	printf("  bios_geom=%lu/%lu/%lu\n",d->bios_cyl,d->bios_hd,d->bios_sect);
131	Debug_Chunk(d->chunks);
132}
133
134void
135Free_Disk(struct disk *d)
136{
137	if(d->chunks)
138		Free_Chunk(d->chunks);
139	if(d->name)
140		free(d->name);
141	free(d);
142}
143
144struct disk *
145Clone_Disk(struct disk *d)
146{
147	struct disk *d2;
148
149	d2 = (struct disk*) malloc(sizeof *d2);
150	if(!d2) err(1,"malloc failed");
151	*d2 = *d;
152	d2->name = strdup(d2->name);
153	d2->chunks = Clone_Chunk(d2->chunks);
154	return d2;
155}
156
157void
158Collapse_Disk(struct disk *d)
159{
160
161	while(Collapse_Chunk(d,d->chunks))
162		;
163}
164
165int
166Aligned(struct disk *d, u_long offset)
167{
168	if (offset % d->bios_sect)
169		return 0;
170	return 1;
171}
172
173u_long
174Prev_Aligned(struct disk *d, u_long offset)
175{
176	return (offset / d->bios_sect) * d->bios_sect;
177}
178
179u_long
180Next_Aligned(struct disk *d, u_long offset)
181{
182	return Prev_Aligned(d,offset + d->bios_sect);
183}
184