]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - lib/libdisk/open_ia64_disk.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / lib / libdisk / open_ia64_disk.c
1 /*
2  * Copyright (c) 2003 Marcel Moolenaar
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/types.h>
31 #include <sys/disklabel.h>
32 #include <sys/diskmbr.h>
33 #include <sys/gpt.h>
34 #include <sys/uuid.h>
35
36 #include <fcntl.h>
37 #include <inttypes.h>
38 #include <paths.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <unistd.h>
43
44 #include "libdisk.h"
45
46 static struct disk *
47 parse_disk(char *conftxt, const char *name)
48 {
49         char devname[64];
50         struct disk *disk;
51         struct dos_partition *part;
52         struct gpt_hdr *gpt;
53         char *buffer, *p, *q;
54         int fd, i;
55
56         disk = (struct disk *)calloc(sizeof *disk, 1);
57         if (disk == NULL)
58                 return (NULL);
59
60         disk->name = strdup(name);
61         p = strsep(&conftxt, " ");                      /* media size */
62         disk->media_size = strtoimax(p, &q, 0);
63         if (*q)
64                 goto fail;
65
66         p = strsep(&conftxt, " ");                      /* sector size */
67         disk->sector_size = strtoul(p, &q, 0);
68         if (*q)
69                 goto fail;
70
71         if (disk->sector_size == 0)
72                 disk->sector_size = 512;
73
74         if (disk->media_size % disk->sector_size)
75                 goto fail;
76
77         /*
78          * We need to read the disk to get GPT specific information.
79          */
80
81         snprintf(devname, sizeof(devname), "%s%s", _PATH_DEV, name);
82         fd = open(devname, O_RDONLY);
83         if (fd == -1)
84                 goto fail;
85         buffer = malloc(2 * disk->sector_size);
86         if (buffer == NULL) {
87                 close (fd);
88                 goto fail;
89         }
90         if (read(fd, buffer, 2 * disk->sector_size) == -1) {
91                 free(buffer);
92                 close(fd);
93                 goto fail;
94         }
95         close(fd);
96
97         gpt = (struct gpt_hdr *)(buffer + disk->sector_size);
98         if (memcmp(gpt->hdr_sig, GPT_HDR_SIG, sizeof(gpt->hdr_sig))) {
99                 /*
100                  * No GPT present. Check if the MBR is empty (if present)
101                  * or is a PMBR before declaring this disk as empty. If
102                  * the MBR isn't empty, bail out. Let's not risk nuking a
103                  * disk.
104                  */
105                 if (*(u_short *)(buffer + DOSMAGICOFFSET) == DOSMAGIC) {
106                         for (i = 0; i < 4; i++) {
107                                 part = (struct dos_partition *)
108                                     (buffer + DOSPARTOFF + i * DOSPARTSIZE);
109                                 if (part->dp_typ != 0 &&
110                                     part->dp_typ != DOSPTYP_PMBR)
111                                         break;
112                         }
113                         if (i < 4) {
114                                 free(buffer);
115                                 goto fail;
116                         }
117                 }
118                 disk->gpt_size = 128;
119                 disk->lba_start = (disk->gpt_size * sizeof(struct gpt_ent)) /
120                     disk->sector_size + 2;
121                 disk->lba_end = (disk->media_size / disk->sector_size) -
122                     disk->lba_start;
123         } else {
124                 disk->lba_start = gpt->hdr_lba_start;
125                 disk->lba_end = gpt->hdr_lba_end;
126                 disk->gpt_size = gpt->hdr_entries;
127         }
128         free(buffer);
129         Add_Chunk(disk, disk->lba_start, disk->lba_end - disk->lba_start + 1,
130             name, whole, 0, 0, "-");
131         return (disk);
132
133 fail:
134         free(disk->name);
135         free(disk);
136         return (NULL);
137 }
138
139 struct disk *
140 Int_Open_Disk(const char *name, char *conftxt)
141 {
142         struct chunk chunk;
143         struct disk *disk;
144         char *p, *q, *r, *s, *sd;
145         u_long i;
146
147         p = conftxt;
148         while (p != NULL && *p != 0) {
149                 q = strsep(&p, " ");
150                 if (strcmp(q, "0") == 0) {
151                         q = strsep(&p, " ");
152                         if (strcmp(q, "DISK") == 0) {
153                                 q = strsep(&p, " ");
154                                 if (strcmp(q, name) == 0)
155                                         break;
156                         }
157                 }
158                 p = strchr(p, '\n');
159                 if (p != NULL && *p == '\n')
160                         p++;
161                 conftxt = p;
162         }
163         if (p == NULL || *p == 0)
164                 return (NULL);
165
166         conftxt = strchr(p, '\n');
167         if (conftxt != NULL)
168                 *conftxt++ = '\0';
169
170         disk = parse_disk(p, name);
171         if (disk == NULL)
172                 return (NULL);
173
174         while (conftxt != NULL && *conftxt != 0) {
175                 p = conftxt;
176                 conftxt = strchr(p, '\n');
177                 if (conftxt != NULL)
178                         *conftxt++ = '\0';
179
180                 /*
181                  * 1 PART da0p4 34359738368 512
182                  *      i 4 o 52063912960 ty freebsd-ufs
183                  *      xs GPT xt 516e7cb6-6ecf-11d6-8ff8-00022d09712b
184                  */
185                 sd = strsep(&p, " ");                   /* depth */
186                 if (strcmp(sd, "0") == 0)
187                         break;
188
189                 q = strsep(&p, " ");                    /* type */
190                 if (strcmp(q, "PART") != 0)
191                         continue;
192
193                 chunk.name = strsep(&p, " ");           /* name */
194
195                 q = strsep(&p, " ");                    /* length */
196                 i = strtoimax(q, &r, 0);
197                 if (*r)
198                         abort();
199                 chunk.end = i / disk->sector_size;
200
201                 q = strsep(&p, " ");                    /* sector size */
202
203                 for (;;) {
204                         q = strsep(&p, " ");
205                         if (q == NULL)
206                                 break;
207                         r = strsep(&p, " ");
208                         i = strtoimax(r, &s, 0);
209                         if (strcmp(q, "ty") == 0 && *s != '\0') {
210                                 if (!strcmp(r, "efi"))
211                                         chunk.type = efi;
212                                 else if (!strcmp(r, "freebsd")) {
213                                         chunk.type = freebsd;
214                                         chunk.subtype = 0xa5;
215                                 } else if (!strcmp(r, "freebsd-swap")) {
216                                         chunk.type = part;
217                                         chunk.subtype = FS_SWAP;
218                                 } else if (!strcmp(r, "freebsd-ufs")) {
219                                         chunk.type = part;
220                                         chunk.subtype = FS_BSDFFS;
221                                 } else {
222                                         chunk.type = part;
223                                         chunk.subtype = FS_OTHER;
224                                 }
225                         } else {
226                                 if (!strcmp(q, "o"))
227                                         chunk.offset = i / disk->sector_size;
228                                 else if (!strcmp(q, "i"))
229                                         chunk.flags = CHUNK_ITOF(i) |
230                                             CHUNK_HAS_INDEX;
231                         }
232                 }
233
234                 Add_Chunk(disk, chunk.offset, chunk.end, chunk.name,
235                     chunk.type, chunk.subtype, chunk.flags, 0);
236         }
237
238         return (disk);
239 }