source: grub-pc/trunk/fuentes/grub-core/kern/partition.c @ 22

Last change on this file since 22 was 22, checked in by mabarracus, 4 years ago

updated version and apply net.ifnames=0 into debian/rules

File size: 6.4 KB
Line 
1/*
2 *  GRUB  --  GRand Unified Bootloader
3 *  Copyright (C) 2004,2007  Free Software Foundation, Inc.
4 *
5 *  GRUB is free software: you can redistribute it and/or modify
6 *  it under the terms of the GNU General Public License as published by
7 *  the Free Software Foundation, either version 3 of the License, or
8 *  (at your option) any later version.
9 *
10 *  GRUB is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 *  GNU General Public License for more details.
14 *
15 *  You should have received a copy of the GNU General Public License
16 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <grub/misc.h>
20#include <grub/mm.h>
21#include <grub/partition.h>
22#include <grub/disk.h>
23#include <grub/i18n.h>
24
25#ifdef GRUB_UTIL
26#include <grub/util/misc.h>
27#endif
28
29grub_partition_map_t grub_partition_map_list;
30
31/*
32 * Checks that disk->partition contains part.  This function assumes that the
33 * start of part is relative to the start of disk->partition.  Returns 1 if
34 * disk->partition is null.
35 */
36static int
37grub_partition_check_containment (const grub_disk_t disk,
38                                  const grub_partition_t part)
39{
40  if (disk->partition == NULL)
41    return 1;
42
43  if (part->start + part->len > disk->partition->len)
44    {
45      char *partname;
46
47      partname = grub_partition_get_name (disk->partition);
48      grub_dprintf ("partition", "sub-partition %s%d of (%s,%s) ends after parent.\n",
49                    part->partmap->name, part->number + 1, disk->name, partname);
50#ifdef GRUB_UTIL
51      grub_util_warn (_("Discarding improperly nested partition (%s,%s,%s%d)"),
52                      disk->name, partname, part->partmap->name, part->number + 1);
53#endif
54      grub_free (partname);
55
56      return 0;
57    }
58
59  return 1;
60}
61
62/* Context for grub_partition_map_probe.  */
63struct grub_partition_map_probe_ctx
64{
65  int partnum;
66  grub_partition_t p;
67};
68
69/* Helper for grub_partition_map_probe.  */
70static int
71probe_iter (grub_disk_t dsk, const grub_partition_t partition, void *data)
72{
73  struct grub_partition_map_probe_ctx *ctx = data;
74
75  if (ctx->partnum != partition->number)
76    return 0;
77
78  if (!(grub_partition_check_containment (dsk, partition)))
79    return 0;
80
81  ctx->p = (grub_partition_t) grub_malloc (sizeof (*ctx->p));
82  if (! ctx->p)
83    return 1;
84
85  grub_memcpy (ctx->p, partition, sizeof (*ctx->p));
86  return 1;
87}
88
89static grub_partition_t
90grub_partition_map_probe (const grub_partition_map_t partmap,
91                          grub_disk_t disk, int partnum)
92{
93  struct grub_partition_map_probe_ctx ctx = {
94    .partnum = partnum,
95    .p = 0
96  };
97
98  partmap->iterate (disk, probe_iter, &ctx);
99  if (grub_errno)
100    goto fail;
101
102  return ctx.p;
103
104 fail:
105  grub_free (ctx.p);
106  return 0;
107}
108
109grub_partition_t
110grub_partition_probe (struct grub_disk *disk, const char *str)
111{
112  grub_partition_t part = 0;
113  grub_partition_t curpart = 0;
114  grub_partition_t tail;
115  const char *ptr;
116
117  part = tail = disk->partition;
118
119  for (ptr = str; *ptr;)
120    {
121      grub_partition_map_t partmap;
122      int num;
123      const char *partname, *partname_end;
124
125      partname = ptr;
126      while (*ptr && grub_isalpha (*ptr))
127        ptr++;
128      partname_end = ptr; 
129      num = grub_strtoul (ptr, (char **) &ptr, 0) - 1;
130
131      curpart = 0;
132      /* Use the first partition map type found.  */
133      FOR_PARTITION_MAPS(partmap)
134      {
135        if (partname_end != partname &&
136            (grub_strncmp (partmap->name, partname, partname_end - partname)
137             != 0 || partmap->name[partname_end - partname] != 0))
138          continue;
139
140        disk->partition = part;
141        curpart = grub_partition_map_probe (partmap, disk, num);
142        disk->partition = tail;
143        if (curpart)
144          break;
145
146        if (grub_errno == GRUB_ERR_BAD_PART_TABLE)
147          {
148            /* Continue to next partition map type.  */
149            grub_errno = GRUB_ERR_NONE;
150            continue;
151          }
152
153        break;
154      }
155
156      if (! curpart)
157        {
158          while (part)
159            {
160              curpart = part->parent;
161              grub_free (part);
162              part = curpart;
163            }
164          return 0;
165        }
166      curpart->parent = part;
167      part = curpart;
168      if (! ptr || *ptr != ',')
169        break;
170      ptr++;
171    }
172
173  return part;
174}
175
176/* Context for grub_partition_iterate.  */
177struct grub_partition_iterate_ctx
178{
179  int ret;
180  grub_partition_iterate_hook_t hook;
181  void *hook_data;
182};
183
184/* Helper for grub_partition_iterate.  */
185static int
186part_iterate (grub_disk_t dsk, const grub_partition_t partition, void *data)
187{
188  struct grub_partition_iterate_ctx *ctx = data;
189  struct grub_partition p = *partition;
190
191  if (!(grub_partition_check_containment (dsk, partition)))
192    return 0;
193
194  p.parent = dsk->partition;
195  dsk->partition = 0;
196  if (ctx->hook (dsk, &p, ctx->hook_data))
197    {
198      ctx->ret = 1;
199      return 1;
200    }
201  if (p.start != 0)
202    {
203      const struct grub_partition_map *partmap;
204      dsk->partition = &p;
205      FOR_PARTITION_MAPS(partmap)
206      {
207        grub_err_t err;
208        err = partmap->iterate (dsk, part_iterate, ctx);
209        if (err)
210          grub_errno = GRUB_ERR_NONE;
211        if (ctx->ret)
212          break;
213      }
214    }
215  dsk->partition = p.parent;
216  return ctx->ret;
217}
218
219int
220grub_partition_iterate (struct grub_disk *disk,
221                        grub_partition_iterate_hook_t hook, void *hook_data)
222{
223  struct grub_partition_iterate_ctx ctx = {
224    .ret = 0,
225    .hook = hook,
226    .hook_data = hook_data
227  };
228  const struct grub_partition_map *partmap;
229
230  FOR_PARTITION_MAPS(partmap)
231  {
232    grub_err_t err;
233    err = partmap->iterate (disk, part_iterate, &ctx);
234    if (err)
235      grub_errno = GRUB_ERR_NONE;
236    if (ctx.ret)
237      break;
238  }
239
240  return ctx.ret;
241}
242
243char *
244grub_partition_get_name (const grub_partition_t partition)
245{
246  char *out = 0, *ptr;
247  grub_size_t needlen = 0;
248  grub_partition_t part;
249  if (!partition)
250    return grub_strdup ("");
251  for (part = partition; part; part = part->parent)
252    /* Even on 64-bit machines this buffer is enough to hold
253       longest number.  */
254    needlen += grub_strlen (part->partmap->name) + 1 + 27;
255  out = grub_malloc (needlen + 1);
256  if (!out)
257    return NULL;
258
259  ptr = out + needlen;
260  *ptr = 0;
261  for (part = partition; part; part = part->parent)
262    {
263      char buf[27];
264      grub_size_t len;
265      grub_snprintf (buf, sizeof (buf), "%d", part->number + 1);
266      len = grub_strlen (buf);
267      ptr -= len;
268      grub_memcpy (ptr, buf, len);
269      len = grub_strlen (part->partmap->name);
270      ptr -= len;
271      grub_memcpy (ptr, part->partmap->name, len);
272      *--ptr = ',';
273    }
274  grub_memmove (out, ptr + 1, out + needlen - ptr);
275  return out;
276}
Note: See TracBrowser for help on using the repository browser.