1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
Upstream: http://lists.gnu.org/archive/html/grub-devel/2009-09/msg00210.html
Description: If you set root after running loopback, any attempts to open
files on the loopback device resolve the loopback file name relative to the
*new* root, not the root at the time loopback was invoked, and so the above
recurses until it runs out of stack. This causes problems for Wubi. I think
it's fairly clear that only the root that was in place when you ran
loopback should be relevant to the loopback file name.
diff -Nur -x '*.orig' -x '*~' grub2-1.97~beta2/disk/loopback.c grub2-1.97~beta2.new/disk/loopback.c
--- grub2-1.97~beta2/disk/loopback.c 2009-06-10 22:04:23.000000000 +0100
+++ grub2-1.97~beta2.new/disk/loopback.c 2009-09-10 21:42:56.000000000 +0100
@@ -28,6 +28,7 @@
{
char *devname;
char *filename;
+ grub_file_t file;
int has_partitions;
struct grub_loopback *next;
};
@@ -61,6 +62,7 @@
/* Remove the device from the list. */
*prev = dev->next;
+ grub_file_close (dev->file);
grub_free (dev->devname);
grub_free (dev->filename);
grub_free (dev);
@@ -90,9 +92,6 @@
if (! file)
return grub_errno;
- /* Close the file, the only reason for opening it is validation. */
- grub_file_close (file);
-
/* First try to replace the old device. */
for (newdev = loopback_list; newdev; newdev = newdev->next)
if (grub_strcmp (newdev->devname, args[0]) == 0)
@@ -102,10 +101,12 @@
{
char *newname = grub_strdup (args[1]);
if (! newname)
- return grub_errno;
+ goto fail;
grub_free (newdev->filename);
newdev->filename = newname;
+ grub_file_close (newdev->file);
+ newdev->file = file;
/* Set has_partitions when `--partitions' was used. */
newdev->has_partitions = state[1].set;
@@ -116,13 +117,13 @@
/* Unable to replace it, make a new entry. */
newdev = grub_malloc (sizeof (struct grub_loopback));
if (! newdev)
- return grub_errno;
+ goto fail;
newdev->devname = grub_strdup (args[0]);
if (! newdev->devname)
{
grub_free (newdev);
- return grub_errno;
+ goto fail;
}
newdev->filename = grub_strdup (args[1]);
@@ -130,9 +131,11 @@
{
grub_free (newdev->devname);
grub_free (newdev);
- return grub_errno;
+ goto fail;
}
+ newdev->file = file;
+
/* Set has_partitions when `--partitions' was used. */
newdev->has_partitions = state[1].set;
@@ -141,6 +144,10 @@
loopback_list = newdev;
return 0;
+
+fail:
+ grub_file_close (file);
+ return grub_errno;
}
@@ -159,7 +166,6 @@
static grub_err_t
grub_loopback_open (const char *name, grub_disk_t disk)
{
- grub_file_t file;
struct grub_loopback *dev;
for (dev = loopback_list; dev; dev = dev->next)
@@ -169,29 +175,17 @@
if (! dev)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Can't open device");
- file = grub_file_open (dev->filename);
- if (! file)
- return grub_errno;
-
/* Use the filesize for the disk size, round up to a complete sector. */
- disk->total_sectors = ((file->size + GRUB_DISK_SECTOR_SIZE - 1)
+ disk->total_sectors = ((dev->file->size + GRUB_DISK_SECTOR_SIZE - 1)
/ GRUB_DISK_SECTOR_SIZE);
disk->id = (unsigned long) dev;
disk->has_partitions = dev->has_partitions;
- disk->data = file;
+ disk->data = dev->file;
return 0;
}
-static void
-grub_loopback_close (grub_disk_t disk)
-{
- grub_file_t file = (grub_file_t) disk->data;
-
- grub_file_close (file);
-}
-
static grub_err_t
grub_loopback_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
@@ -233,7 +227,6 @@
.id = GRUB_DISK_DEVICE_LOOPBACK_ID,
.iterate = grub_loopback_iterate,
.open = grub_loopback_open,
- .close = grub_loopback_close,
.read = grub_loopback_read,
.write = grub_loopback_write,
.next = 0
|