merge with mainline

This commit is contained in:
BVK Chaitanya 2010-06-08 10:06:14 +05:30
commit e5dacf260a
29 changed files with 2780 additions and 319 deletions

View file

@ -80,6 +80,86 @@ xgetcwd (void)
return path;
}
#ifdef __linux__
/* Statting something on a btrfs filesystem always returns a virtual device
major/minor pair rather than the real underlying device, because btrfs
can span multiple underlying devices (and even if it's currently only
using a single device it can be dynamically extended onto another). We
can't deal with the multiple-device case yet, but in the meantime, we can
at least cope with the single-device case by scanning
/proc/self/mountinfo. */
static char *
find_root_device_from_mountinfo (const char *dir)
{
FILE *fp;
char *buf = NULL;
size_t len = 0;
char *ret = NULL;
fp = fopen ("/proc/self/mountinfo", "r");
if (! fp)
return NULL; /* fall through to other methods */
while (getline (&buf, &len, fp) > 0)
{
int mnt_id, parent_mnt_id;
unsigned int major, minor;
char enc_root[PATH_MAX], enc_path[PATH_MAX];
int count;
size_t enc_path_len;
const char *sep;
char fstype[PATH_MAX], device[PATH_MAX];
struct stat st;
if (sscanf (buf, "%d %d %u:%u %s %s%n",
&mnt_id, &parent_mnt_id, &major, &minor, enc_root, enc_path,
&count) < 6)
continue;
if (strcmp (enc_root, "/") != 0)
continue; /* only a subtree is mounted */
enc_path_len = strlen (enc_path);
if (strncmp (dir, enc_path, enc_path_len) != 0 ||
(dir[enc_path_len] && dir[enc_path_len] != '/'))
continue;
/* This is a parent of the requested directory. /proc/self/mountinfo
is in mount order, so it must be the closest parent we've
encountered so far. If it's virtual, return its device node;
otherwise, carry on to try to find something closer. */
free (ret);
ret = NULL;
if (major != 0)
continue; /* not a virtual device */
sep = strstr (buf + count, " - ");
if (!sep)
continue;
sep += sizeof (" - ") - 1;
if (sscanf (sep, "%s %s", fstype, device) != 2)
continue;
if (stat (device, &st) < 0)
continue;
if (!S_ISBLK (st.st_mode))
continue; /* not a block device */
ret = strdup (device);
}
free (buf);
fclose (fp);
return ret;
}
#endif /* __linux__ */
#ifdef __MINGW32__
static char *
@ -366,6 +446,12 @@ grub_guess_root_device (const char *dir)
#else /* !__GNU__ */
struct stat st;
#ifdef __linux__
os_dev = find_root_device_from_mountinfo (dir);
if (os_dev)
return os_dev;
#endif /* __linux__ */
if (stat (dir, &st) < 0)
grub_util_error ("cannot stat `%s'", dir);

View file

@ -413,7 +413,11 @@ devmapper_fail:
if (fd == -1)
{
grub_error (GRUB_ERR_BAD_DEVICE,
# if !defined(__NetBSD__)
"cannot open `%s' while attempting to get disk geometry", dev);
# else /* defined(__NetBSD__) */
"cannot open `%s' while attempting to get disk label", dev);
# endif /* !defined(__NetBSD__) */
return 0;
}
@ -425,7 +429,11 @@ devmapper_fail:
# endif /* !defined(__NetBSD__) */
{
grub_error (GRUB_ERR_BAD_DEVICE,
# if !defined(__NetBSD__)
"cannot get disk geometry of `%s'", dev);
# else /* defined(__NetBSD__) */
"cannot get disk label of `%s'", dev);
# endif /* !defined(__NetBSD__) */
close (fd);
return 0;
}
@ -1256,22 +1264,28 @@ devmapper_out:
return path;
#elif defined(__NetBSD__)
/* NetBSD uses "/dev/r[wsc]d[0-9]+[a-z]". */
/* NetBSD uses "/dev/r[a-z]+[0-9][a-z]". */
char *path = xstrdup (os_dev);
if (strncmp ("/dev/rwd", path, 8) == 0 ||
strncmp ("/dev/rsd", path, 8) == 0 ||
strncmp ("/dev/rcd", path, 8) == 0)
if (strncmp ("/dev/r", path, sizeof("/dev/r") - 1) == 0 &&
(path[sizeof("/dev/r") - 1] >= 'a' && path[sizeof("/dev/r") - 1] <= 'z') &&
strncmp ("fd", path + sizeof("/dev/r") - 1, sizeof("fd") - 1) != 0) /* not a floppy device name */
{
char *q;
q = path + strlen(path) - 1; /* last character */
if (grub_isalpha(*q) && grub_isdigit(*(q-1)))
{
int rawpart = -1;
char *p;
for (p = path + sizeof("/dev/r"); *p >= 'a' && *p <= 'z'; p++);
if (grub_isdigit(*p))
{
p++;
if ((*p >= 'a' && *p <= 'z') && (*(p+1) == '\0'))
{
/* path matches the required regular expression and
p points to its last character. */
int rawpart = -1;
# ifdef HAVE_GETRAWPARTITION
rawpart = getrawpartition();
rawpart = getrawpartition();
# endif /* HAVE_GETRAWPARTITION */
if (rawpart >= 0)
*q = 'a' + rawpart;
if (rawpart >= 0)
*p = 'a' + rawpart;
}
}
}
return path;
@ -1429,8 +1443,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
return name;
# else /* defined(__NetBSD__) */
/* Since os_dev and convert_system_partition_to_system_disk (os_dev) are
* different, we know that os_dev is of the form /dev/r[wsc]d[0-9]+[a-z]
* and in particular it cannot be a floppy device. */
* different, we know that os_dev cannot be a floppy device. */
# endif /* !defined(__NetBSD__) */
start = find_partition_start (os_dev);