~ubuntu-branches/ubuntu/trusty/grub2/trusty

« back to all changes in this revision

Viewing changes to .pc/mount_readdir_symlink_failures.patch/util/grub-mount.c

  • Committer: Package Import Robot
  • Author(s): Colin Watson
  • Date: 2014-01-16 15:18:04 UTC
  • mfrom: (17.6.38 experimental)
  • Revision ID: package-import@ubuntu.com-20140116151804-3foouk7fpqcq3sxx
Tags: 2.02~beta2-2
* Convert patch handling to git-dpm.
* Add bi-endian support to ELF parser (Tomohiro B Berry).
* Adjust restore_mkdevicemap.patch to mark get_kfreebsd_version as static,
  to appease "gcc -Werror=missing-prototypes".
* Cherry-pick from upstream:
  - Change grub-macbless' manual page section to 8.
* Install grub-glue-efi, grub-macbless, grub-render-label, and
  grub-syslinux2cfg.
* grub-shell: Pass -no-pad to xorriso when building floppy images.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* grub-mount.c - FUSE driver for filesystems that GRUB understands */
2
 
/*
3
 
 *  GRUB  --  GRand Unified Bootloader
4
 
 *  Copyright (C) 2008,2009,2010 Free Software Foundation, Inc.
5
 
 *
6
 
 *  GRUB is free software: you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation, either version 3 of the License, or
9
 
 *  (at your option) any later version.
10
 
 *
11
 
 *  GRUB is distributed in the hope that it will be useful,
12
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 *  GNU General Public License for more details.
15
 
 *
16
 
 *  You should have received a copy of the GNU General Public License
17
 
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
18
 
 */
19
 
#define FUSE_USE_VERSION 26
20
 
#include <config.h>
21
 
#include <grub/types.h>
22
 
#include <grub/emu/misc.h>
23
 
#include <grub/util/misc.h>
24
 
#include <grub/misc.h>
25
 
#include <grub/device.h>
26
 
#include <grub/disk.h>
27
 
#include <grub/file.h>
28
 
#include <grub/fs.h>
29
 
#include <grub/env.h>
30
 
#include <grub/term.h>
31
 
#include <grub/mm.h>
32
 
#include <grub/lib/hexdump.h>
33
 
#include <grub/crypto.h>
34
 
#include <grub/command.h>
35
 
#include <grub/zfs/zfs.h>
36
 
#include <grub/i18n.h>
37
 
#include <fuse/fuse.h>
38
 
 
39
 
#include <stdio.h>
40
 
#include <unistd.h>
41
 
#include <string.h>
42
 
#include <stdlib.h>
43
 
 
44
 
#include "progname.h"
45
 
#include "argp.h"
46
 
 
47
 
static const char *root = NULL;
48
 
grub_device_t dev = NULL;
49
 
grub_fs_t fs = NULL;
50
 
static char **images = NULL;
51
 
static char *debug_str = NULL;
52
 
static char **fuse_args = NULL;
53
 
static int fuse_argc = 0;
54
 
static int num_disks = 0;
55
 
static int mount_crypt = 0;
56
 
 
57
 
static grub_err_t
58
 
execute_command (const char *name, int n, char **args)
59
 
{
60
 
  grub_command_t cmd;
61
 
 
62
 
  cmd = grub_command_find (name);
63
 
  if (! cmd)
64
 
    grub_util_error (_("can't find command `%s'"), name);
65
 
 
66
 
  return (cmd->func) (cmd, n, args);
67
 
}
68
 
 
69
 
/* Translate GRUB error numbers into OS error numbers.  Print any unexpected
70
 
   errors.  */
71
 
static int
72
 
translate_error (void)
73
 
{
74
 
  int ret;
75
 
 
76
 
  switch (grub_errno)
77
 
    {
78
 
      case GRUB_ERR_NONE:
79
 
        ret = 0;
80
 
        break;
81
 
 
82
 
      case GRUB_ERR_OUT_OF_MEMORY:
83
 
        grub_print_error ();
84
 
        ret = -ENOMEM;
85
 
        break;
86
 
 
87
 
      case GRUB_ERR_BAD_FILE_TYPE:
88
 
        /* This could also be EISDIR.  Take a guess.  */
89
 
        ret = -ENOTDIR;
90
 
        break;
91
 
 
92
 
      case GRUB_ERR_FILE_NOT_FOUND:
93
 
        ret = -ENOENT;
94
 
        break;
95
 
 
96
 
      case GRUB_ERR_FILE_READ_ERROR:
97
 
      case GRUB_ERR_READ_ERROR:
98
 
      case GRUB_ERR_IO:
99
 
        grub_print_error ();
100
 
        ret = -EIO;
101
 
        break;
102
 
 
103
 
      case GRUB_ERR_SYMLINK_LOOP:
104
 
        ret = -ELOOP;
105
 
        break;
106
 
 
107
 
      default:
108
 
        grub_print_error ();
109
 
        ret = -EINVAL;
110
 
        break;
111
 
    }
112
 
 
113
 
  /* Any previous errors were handled.  */
114
 
  grub_errno = GRUB_ERR_NONE;
115
 
 
116
 
  return ret;
117
 
}
118
 
 
119
 
static int
120
 
fuse_getattr (const char *path, struct stat *st)
121
 
{
122
 
  char *filename, *pathname, *path2;
123
 
  const char *pathname_t;
124
 
  struct grub_dirhook_info file_info;
125
 
  int file_exists = 0;
126
 
  
127
 
  /* A hook for iterating directories. */
128
 
  auto int find_file (const char *cur_filename,
129
 
                      const struct grub_dirhook_info *info);
130
 
  int find_file (const char *cur_filename,
131
 
                 const struct grub_dirhook_info *info)
132
 
  {
133
 
    if ((info->case_insensitive ? grub_strcasecmp (cur_filename, filename)
134
 
         : grub_strcmp (cur_filename, filename)) == 0)
135
 
      {
136
 
        file_info = *info;
137
 
        file_exists = 1;
138
 
        return 1;
139
 
      }
140
 
    return 0;
141
 
  }
142
 
 
143
 
  if (path[0] == '/' && path[1] == 0)
144
 
    {
145
 
      st->st_dev = 0;
146
 
      st->st_ino = 0;
147
 
      st->st_mode = 0555 | S_IFDIR;
148
 
      st->st_uid = 0;
149
 
      st->st_gid = 0;
150
 
      st->st_rdev = 0;
151
 
      st->st_size = 0;
152
 
      st->st_blksize = 512;
153
 
      st->st_blocks = (st->st_blksize + 511) >> 9;
154
 
      st->st_atime = st->st_mtime = st->st_ctime = 0;
155
 
      return 0;
156
 
    }
157
 
 
158
 
  file_exists = 0;
159
 
 
160
 
  pathname_t = grub_strchr (path, ')');
161
 
  if (! pathname_t)
162
 
    pathname_t = path;
163
 
  else
164
 
    pathname_t++;
165
 
  pathname = xstrdup (pathname_t);
166
 
  
167
 
  /* Remove trailing '/'. */
168
 
  while (*pathname && pathname[grub_strlen (pathname) - 1] == '/')
169
 
    pathname[grub_strlen (pathname) - 1] = 0;
170
 
 
171
 
  /* Split into path and filename. */
172
 
  filename = grub_strrchr (pathname, '/');
173
 
  if (! filename)
174
 
    {
175
 
      path2 = grub_strdup ("/");
176
 
      filename = pathname;
177
 
    }
178
 
  else
179
 
    {
180
 
      filename++;
181
 
      path2 = grub_strdup (pathname);
182
 
      path2[filename - pathname] = 0;
183
 
    }
184
 
 
185
 
  /* It's the whole device. */
186
 
  (fs->dir) (dev, path2, find_file);
187
 
 
188
 
  grub_free (path2);
189
 
  if (!file_exists)
190
 
    {
191
 
      grub_errno = GRUB_ERR_NONE;
192
 
      return -ENOENT;
193
 
    }
194
 
  st->st_dev = 0;
195
 
  st->st_ino = 0;
196
 
  st->st_mode = file_info.dir ? (0555 | S_IFDIR) : (0444 | S_IFREG);
197
 
  st->st_uid = 0;
198
 
  st->st_gid = 0;
199
 
  st->st_rdev = 0;
200
 
  if (!file_info.dir)
201
 
    {
202
 
      grub_file_t file;
203
 
      file = grub_file_open (path);
204
 
      if (! file)
205
 
        return translate_error ();
206
 
      st->st_size = file->size;
207
 
      grub_file_close (file);
208
 
    }
209
 
  else
210
 
    st->st_size = 0;
211
 
  st->st_blksize = 512;
212
 
  st->st_blocks = (st->st_size + 511) >> 9;
213
 
  st->st_atime = st->st_mtime = st->st_ctime = file_info.mtimeset
214
 
    ? file_info.mtime : 0;
215
 
  grub_errno = GRUB_ERR_NONE;
216
 
  return 0;
217
 
}
218
 
 
219
 
static int
220
 
fuse_opendir (const char *path, struct fuse_file_info *fi) 
221
 
{
222
 
  return 0;
223
 
}
224
 
 
225
 
/* FIXME */
226
 
static grub_file_t files[65536];
227
 
static int first_fd = 1;
228
 
 
229
 
static int 
230
 
fuse_open (const char *path, struct fuse_file_info *fi __attribute__ ((unused)))
231
 
{
232
 
  grub_file_t file;
233
 
  file = grub_file_open (path);
234
 
  if (! file)
235
 
    return translate_error ();
236
 
  files[first_fd++] = file;
237
 
  fi->fh = first_fd;
238
 
  files[first_fd++] = file;
239
 
  grub_errno = GRUB_ERR_NONE;
240
 
  return 0;
241
 
242
 
 
243
 
static int 
244
 
fuse_read (const char *path, char *buf, size_t sz, off_t off,
245
 
           struct fuse_file_info *fi)
246
 
{
247
 
  grub_file_t file = files[fi->fh];
248
 
  grub_ssize_t size;
249
 
 
250
 
  if (off > file->size)
251
 
    return -EINVAL;
252
 
 
253
 
  file->offset = off;
254
 
  
255
 
  size = grub_file_read (file, buf, sz);
256
 
  if (size < 0)
257
 
    return translate_error ();
258
 
  else
259
 
    {
260
 
      grub_errno = GRUB_ERR_NONE;
261
 
      return size;
262
 
    }
263
 
264
 
 
265
 
static int 
266
 
fuse_release (const char *path, struct fuse_file_info *fi)
267
 
{
268
 
  grub_file_close (files[fi->fh]);
269
 
  files[fi->fh] = NULL;
270
 
  grub_errno = GRUB_ERR_NONE;
271
 
  return 0;
272
 
}
273
 
 
274
 
static int 
275
 
fuse_readdir (const char *path, void *buf,
276
 
              fuse_fill_dir_t fill, off_t off, struct fuse_file_info *fi)
277
 
{
278
 
  char *pathname;
279
 
 
280
 
  auto int call_fill (const char *filename,
281
 
                      const struct grub_dirhook_info *info);
282
 
  int call_fill (const char *filename, const struct grub_dirhook_info *info)
283
 
  {
284
 
    struct stat st;
285
 
    grub_memset (&st, 0, sizeof (st));
286
 
    st.st_mode = info->dir ? (0555 | S_IFDIR) : (0444 | S_IFREG);
287
 
    if (!info->dir)
288
 
      {
289
 
        grub_file_t file;
290
 
        char *tmp;
291
 
        tmp = xasprintf ("%s/%s", path, filename);
292
 
        file = grub_file_open (tmp);
293
 
        free (tmp);
294
 
        if (! file)
295
 
          return translate_error ();
296
 
        st.st_size = file->size;
297
 
        grub_file_close (file);
298
 
      }
299
 
    st.st_blksize = 512;
300
 
    st.st_blocks = (st.st_size + 511) >> 9;
301
 
    st.st_atime = st.st_mtime = st.st_ctime
302
 
      = info->mtimeset ? info->mtime : 0;
303
 
    fill (buf, filename, &st, 0);
304
 
    return 0;
305
 
  }
306
 
 
307
 
  pathname = xstrdup (path);
308
 
  
309
 
  /* Remove trailing '/'. */
310
 
  while (pathname [0] && pathname[1]
311
 
         && pathname[grub_strlen (pathname) - 1] == '/')
312
 
    pathname[grub_strlen (pathname) - 1] = 0;
313
 
 
314
 
  (fs->dir) (dev, pathname, call_fill);
315
 
  free (pathname);
316
 
  grub_errno = GRUB_ERR_NONE;
317
 
  return 0;
318
 
}
319
 
 
320
 
struct fuse_operations grub_opers = {
321
 
  .getattr = fuse_getattr,
322
 
  .open = fuse_open,
323
 
  .release = fuse_release,
324
 
  .opendir = fuse_opendir,
325
 
  .readdir = fuse_readdir,
326
 
  .read = fuse_read
327
 
};
328
 
 
329
 
static grub_err_t
330
 
fuse_init (void)
331
 
{
332
 
  int i;
333
 
 
334
 
  for (i = 0; i < num_disks; i++)
335
 
    {
336
 
      char *argv[2];
337
 
      char *host_file;
338
 
      char *loop_name;
339
 
      loop_name = grub_xasprintf ("loop%d", i);
340
 
      if (!loop_name)
341
 
        grub_util_error ("%s", grub_errmsg);
342
 
 
343
 
      host_file = grub_xasprintf ("(host)%s", images[i]);
344
 
      if (!host_file)
345
 
        grub_util_error ("%s", grub_errmsg);
346
 
 
347
 
      argv[0] = loop_name;
348
 
      argv[1] = host_file;
349
 
 
350
 
      if (execute_command ("loopback", 2, argv))
351
 
        grub_util_error (_("`loopback' command fails: %s"), grub_errmsg);
352
 
 
353
 
      grub_free (loop_name);
354
 
      grub_free (host_file);
355
 
    }
356
 
 
357
 
  if (mount_crypt)
358
 
    {
359
 
      char *argv[2] = { xstrdup ("-a"), NULL};
360
 
      if (execute_command ("cryptomount", 1, argv))
361
 
          grub_util_error (_("`cryptomount' command fails: %s"),
362
 
                           grub_errmsg);
363
 
      free (argv[0]);
364
 
    }
365
 
 
366
 
  grub_lvm_fini ();
367
 
  grub_mdraid09_fini ();
368
 
  grub_mdraid1x_fini ();
369
 
  grub_diskfilter_fini ();
370
 
  grub_diskfilter_init ();
371
 
  grub_mdraid09_init ();
372
 
  grub_mdraid1x_init ();
373
 
  grub_lvm_init ();
374
 
 
375
 
  dev = grub_device_open (0);
376
 
  if (! dev)
377
 
    return grub_errno;
378
 
 
379
 
  fs = grub_fs_probe (dev);
380
 
  if (! fs)
381
 
    {
382
 
      grub_device_close (dev);
383
 
      return grub_errno;
384
 
    }
385
 
 
386
 
  fuse_main (fuse_argc, fuse_args, &grub_opers, NULL);
387
 
 
388
 
  for (i = 0; i < num_disks; i++)
389
 
    {
390
 
      char *argv[2];
391
 
      char *loop_name;
392
 
 
393
 
      loop_name = grub_xasprintf ("loop%d", i);
394
 
      if (!loop_name)
395
 
        grub_util_error ("%s", grub_errmsg);
396
 
 
397
 
      argv[0] = xstrdup ("-d");
398
 
      argv[1] = loop_name;
399
 
 
400
 
      execute_command ("loopback", 2, argv);
401
 
 
402
 
      grub_free (argv[0]);
403
 
      grub_free (loop_name);
404
 
    }
405
 
 
406
 
  return GRUB_ERR_NONE;
407
 
}
408
 
 
409
 
static struct argp_option options[] = {  
410
 
  {"root",      'r', N_("DEVICE_NAME"), 0, N_("Set root device."),                 2},
411
 
  {"debug",     'd', N_("STRING"),           0, N_("Set debug environment variable."),  2},
412
 
  {"crypto",   'C', NULL, 0, N_("Mount crypto devices."), 2},
413
 
  {"zfs-key",      'K',
414
 
   /* TRANSLATORS: "prompt" is a keyword.  */
415
 
   N_("FILE|prompt"), 0, N_("Load zfs crypto key."),                 2},
416
 
  {"verbose",   'v', NULL, 0, N_("print verbose messages."), 2},
417
 
  {0, 0, 0, 0, 0, 0}
418
 
};
419
 
 
420
 
/* Print the version information.  */
421
 
static void
422
 
print_version (FILE *stream, struct argp_state *state)
423
 
{
424
 
  fprintf (stream, "%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
425
 
}
426
 
void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
427
 
 
428
 
static error_t 
429
 
argp_parser (int key, char *arg, struct argp_state *state)
430
 
{
431
 
  switch (key)
432
 
    {
433
 
    case 'r':
434
 
      root = arg;
435
 
      return 0;
436
 
 
437
 
    case 'K':
438
 
      if (strcmp (arg, "prompt") == 0)
439
 
        {
440
 
          char buf[1024];         
441
 
          grub_printf ("%s", _("Enter ZFS password: "));
442
 
          if (grub_password_get (buf, 1023))
443
 
            {
444
 
              grub_zfs_add_key ((grub_uint8_t *) buf, grub_strlen (buf), 1);
445
 
            }
446
 
        }
447
 
      else
448
 
        {
449
 
          FILE *f;
450
 
          ssize_t real_size;
451
 
          grub_uint8_t buf[1024];
452
 
          f = fopen (arg, "rb");
453
 
          if (!f)
454
 
            {
455
 
              printf (_("%s: error:"), program_name);
456
 
              printf (_("cannot open `%s': %s"), arg, strerror (errno));
457
 
              printf ("\n");
458
 
              return 0;
459
 
            }
460
 
          real_size = fread (buf, 1, 1024, f);
461
 
          if (real_size < 0)
462
 
            {
463
 
              printf (_("%s: error:"), program_name);
464
 
              printf (_("cannot read `%s': %s"), arg,
465
 
                      strerror (errno));
466
 
              printf ("\n");
467
 
              fclose (f);
468
 
              return 0;
469
 
            }
470
 
          grub_zfs_add_key (buf, real_size, 0);
471
 
        }
472
 
      return 0;
473
 
 
474
 
    case 'C':
475
 
      mount_crypt = 1;
476
 
      return 0;
477
 
 
478
 
    case 'd':
479
 
      debug_str = arg;
480
 
      return 0;
481
 
 
482
 
    case 'v':
483
 
      verbosity++;
484
 
      return 0;
485
 
 
486
 
    case ARGP_KEY_ARG:
487
 
      if (arg[0] != '-')
488
 
        break;
489
 
 
490
 
    default:
491
 
      if (!arg)
492
 
        return 0;
493
 
 
494
 
      fuse_args = xrealloc (fuse_args, (fuse_argc + 1) * sizeof (fuse_args[0]));
495
 
      fuse_args[fuse_argc] = xstrdup (arg);
496
 
      fuse_argc++;
497
 
      return 0;
498
 
    }
499
 
 
500
 
  images = xrealloc (images, (num_disks + 1) * sizeof (images[0]));
501
 
  images[num_disks] = canonicalize_file_name (arg);
502
 
  num_disks++;
503
 
 
504
 
  return 0;
505
 
}
506
 
 
507
 
struct argp argp = {
508
 
  options, argp_parser, N_("IMAGE1 [IMAGE2 ...] MOUNTPOINT"),
509
 
  N_("Debug tool for filesystem driver."), 
510
 
  NULL, NULL, NULL
511
 
};
512
 
 
513
 
int
514
 
main (int argc, char *argv[])
515
 
{
516
 
  const char *default_root;
517
 
  char *alloc_root;
518
 
 
519
 
  set_program_name (argv[0]);
520
 
 
521
 
  grub_util_init_nls ();
522
 
 
523
 
  fuse_args = xrealloc (fuse_args, (fuse_argc + 2) * sizeof (fuse_args[0]));
524
 
  fuse_args[fuse_argc] = xstrdup (argv[0]);
525
 
  fuse_argc++;
526
 
  /* Run single-threaded.  */
527
 
  fuse_args[fuse_argc] = xstrdup ("-s");
528
 
  fuse_argc++;
529
 
 
530
 
  argp_parse (&argp, argc, argv, 0, 0, 0);
531
 
  
532
 
  if (num_disks < 2)
533
 
    grub_util_error ("%s", _("need an image and mountpoint"));
534
 
  fuse_args = xrealloc (fuse_args, (fuse_argc + 2) * sizeof (fuse_args[0]));
535
 
  fuse_args[fuse_argc] = images[num_disks - 1];
536
 
  fuse_argc++;
537
 
  num_disks--;
538
 
  fuse_args[fuse_argc] = NULL;
539
 
 
540
 
  /* Initialize all modules. */
541
 
  grub_init_all ();
542
 
 
543
 
  if (debug_str)
544
 
    grub_env_set ("debug", debug_str);
545
 
 
546
 
  default_root = (num_disks == 1) ? "loop0" : "md0";
547
 
  alloc_root = 0;
548
 
  if (root)
549
 
    {
550
 
      if ((*root >= '0') && (*root <= '9'))
551
 
        {
552
 
          alloc_root = xmalloc (strlen (default_root) + strlen (root) + 2);
553
 
 
554
 
          sprintf (alloc_root, "%s,%s", default_root, root);
555
 
          root = alloc_root;
556
 
        }
557
 
    }
558
 
  else
559
 
    root = default_root;
560
 
 
561
 
  grub_env_set ("root", root);
562
 
 
563
 
  if (alloc_root)
564
 
    free (alloc_root);
565
 
 
566
 
  /* Do it.  */
567
 
  fuse_init ();
568
 
  if (grub_errno)
569
 
    {
570
 
      grub_print_error ();
571
 
      return 1;
572
 
    }
573
 
 
574
 
  /* Free resources.  */
575
 
  grub_fini_all ();
576
 
 
577
 
  return 0;
578
 
}