66 |
unsigned long start; |
unsigned long start; |
67 |
}; |
}; |
68 |
# endif /* ! HDIO_GETGEO */ |
# endif /* ! HDIO_GETGEO */ |
69 |
|
# ifndef BLKGETSIZE |
70 |
|
# define BLKGETSIZE _IO(0x12,96) /* return device size */ |
71 |
|
# endif /* ! BLKGETSIZE */ |
72 |
# ifndef MAJOR |
# ifndef MAJOR |
73 |
# ifndef MINORBITS |
# ifndef MINORBITS |
74 |
# define MINORBITS 8 |
# define MINORBITS 8 |
168 |
disk->id = drive; |
disk->id = drive; |
169 |
|
|
170 |
/* Get the size. */ |
/* Get the size. */ |
171 |
if (lstat (map[drive], &st) < 0) |
#ifdef __linux__ |
172 |
|
{ |
173 |
|
unsigned long nr; |
174 |
|
int fd; |
175 |
|
|
176 |
|
fd = open (map[drive], O_RDONLY); |
177 |
|
if (! fd) |
178 |
|
return pupa_error (PUPA_ERR_BAD_DEVICE, "cannot open `%s'", map[drive]); |
179 |
|
|
180 |
|
if (ioctl (fd, BLKGETSIZE, &nr)) |
181 |
|
{ |
182 |
|
close (fd); |
183 |
|
goto fail; |
184 |
|
} |
185 |
|
|
186 |
|
close (fd); |
187 |
|
disk->total_sectors = nr; |
188 |
|
|
189 |
|
pupa_util_info ("the size of %s is %lu", name, disk->total_sectors); |
190 |
|
|
191 |
|
return PUPA_ERR_NONE; |
192 |
|
} |
193 |
|
#else |
194 |
|
# warning "No special routine to get the size of a block device is implemented for your OS. This is not possibly fatal." |
195 |
|
#endif |
196 |
|
|
197 |
|
fail: |
198 |
|
if (stat (map[drive], &st) < 0) |
199 |
return pupa_error (PUPA_ERR_BAD_DEVICE, "cannot stat `%s'", map[drive]); |
return pupa_error (PUPA_ERR_BAD_DEVICE, "cannot stat `%s'", map[drive]); |
200 |
|
|
201 |
if (st.st_blocks) |
if (st.st_blocks) |
204 |
/* Hmm... Use st_size instead. */ |
/* Hmm... Use st_size instead. */ |
205 |
disk->total_sectors = st.st_size >> PUPA_DISK_SECTOR_BITS; |
disk->total_sectors = st.st_size >> PUPA_DISK_SECTOR_BITS; |
206 |
|
|
207 |
|
pupa_util_info ("the size of %s is %lu", name, disk->total_sectors); |
208 |
|
|
209 |
return PUPA_ERR_NONE; |
return PUPA_ERR_NONE; |
210 |
} |
} |
211 |
|
|
217 |
const char *format; |
const char *format; |
218 |
char *p; |
char *p; |
219 |
int i; |
int i; |
220 |
|
char *real_dev; |
221 |
|
|
222 |
|
real_dev = xstrdup (dev); |
223 |
|
|
224 |
if (have_devfs () && strcmp (dev + len - 5, "/disc") == 0) |
if (have_devfs () && strcmp (real_dev + len - 5, "/disc") == 0) |
225 |
{ |
{ |
226 |
p = dev + len - 4; |
p = real_dev + len - 4; |
227 |
format = "part%d"; |
format = "part%d"; |
228 |
} |
} |
229 |
else if ((strncmp (dev + 5, "hd", 2) == 0 |
else if ((strncmp (real_dev + 5, "hd", 2) == 0 |
230 |
|| strncmp (dev + 5, "sd", 2) == 0) |
|| strncmp (real_dev + 5, "sd", 2) == 0) |
231 |
&& dev[7] >= 'a' && dev[7] <= 'z') |
&& real_dev[7] >= 'a' && real_dev[7] <= 'z') |
232 |
{ |
{ |
233 |
p = dev + 8; |
p = real_dev + 8; |
234 |
format = "%d"; |
format = "%d"; |
235 |
} |
} |
236 |
else if (strncmp (dev + 5, "rd/c", 4) == 0) |
else if (strncmp (real_dev + 5, "rd/c", 4) == 0) |
237 |
{ |
{ |
238 |
p = strchr (dev + 9, 'd'); |
p = strchr (real_dev + 9, 'd'); |
239 |
if (! p) |
if (! p) |
240 |
return 0; |
return 0; |
241 |
|
|
246 |
format = "p%d"; |
format = "p%d"; |
247 |
} |
} |
248 |
else |
else |
249 |
return 0; |
{ |
250 |
|
free (real_dev); |
251 |
|
return 0; |
252 |
|
} |
253 |
|
|
254 |
for (i = 0; i < 10000; i++) |
for (i = 1; i < 10000; i++) |
255 |
{ |
{ |
256 |
int fd; |
int fd; |
257 |
struct hd_geometry hdg; |
struct hd_geometry hdg; |
258 |
|
|
259 |
sprintf (p, format, i); |
sprintf (p, format, i); |
260 |
fd = open (dev, O_RDONLY); |
fd = open (real_dev, O_RDONLY); |
261 |
if (! fd) |
if (! fd) |
262 |
return 0; |
{ |
263 |
|
free (real_dev); |
264 |
|
return 0; |
265 |
|
} |
266 |
|
|
267 |
if (ioctl (fd, HDIO_GETGEO, &hdg)) |
if (ioctl (fd, HDIO_GETGEO, &hdg)) |
268 |
{ |
{ |
269 |
close (fd); |
close (fd); |
270 |
|
free (real_dev); |
271 |
return 0; |
return 0; |
272 |
} |
} |
273 |
|
|
274 |
close (fd); |
close (fd); |
275 |
|
|
276 |
if (hdg.start == sector) |
if (hdg.start == sector) |
277 |
return 1; |
{ |
278 |
|
strcpy (dev, real_dev); |
279 |
|
free (real_dev); |
280 |
|
return 1; |
281 |
|
} |
282 |
} |
} |
283 |
|
|
284 |
|
free (real_dev); |
285 |
return 0; |
return 0; |
286 |
} |
} |
287 |
#endif /* __linux__ */ |
#endif /* __linux__ */ |
313 |
is_partition = linux_find_partition (dev, disk->partition->start); |
is_partition = linux_find_partition (dev, disk->partition->start); |
314 |
|
|
315 |
/* Open the partition. */ |
/* Open the partition. */ |
316 |
|
pupa_util_info ("opening the device `%s'", dev); |
317 |
fd = open (dev, flags); |
fd = open (dev, flags); |
318 |
if (fd < 0) |
if (fd < 0) |
319 |
{ |
{ |
320 |
pupa_error (PUPA_ERR_BAD_DEVICE, "cannot open `%s'", dev); |
pupa_error (PUPA_ERR_BAD_DEVICE, "cannot open `%s'", dev); |
321 |
return -1; |
return -1; |
322 |
} |
} |
323 |
|
|
324 |
|
/* Make the buffer cache consistent with the physical disk. */ |
325 |
|
ioctl (fd, BLKFLSBUF, 0); |
326 |
|
|
327 |
if (is_partition) |
if (is_partition) |
328 |
sector -= disk->partition->start; |
sector -= disk->partition->start; |
611 |
if (! realpath (os_dev, path)) |
if (! realpath (os_dev, path)) |
612 |
return 0; |
return 0; |
613 |
|
|
614 |
if (strncmp ("/dev/", path, 4) == 0) |
if (strncmp ("/dev/", path, 5) == 0) |
615 |
{ |
{ |
616 |
p = path + 4; |
p = path + 5; |
617 |
|
|
618 |
if (have_devfs ()) |
if (have_devfs ()) |
619 |
{ |
{ |
704 |
{ |
{ |
705 |
struct stat st; |
struct stat st; |
706 |
int drive; |
int drive; |
707 |
|
|
708 |
if (lstat (os_dev, &st) < 0) |
if (stat (os_dev, &st) < 0) |
709 |
{ |
{ |
710 |
pupa_error (PUPA_ERR_BAD_DEVICE, "cannot stat `%s'", os_dev); |
pupa_error (PUPA_ERR_BAD_DEVICE, "cannot stat `%s'", os_dev); |
711 |
return 0; |
return 0; |
738 |
|
|
739 |
int find_partition (const pupa_partition_t partition) |
int find_partition (const pupa_partition_t partition) |
740 |
{ |
{ |
741 |
|
if (partition->bsd_part < 0) |
742 |
|
pupa_util_info ("DOS partition %d starts from %lu", |
743 |
|
partition->dos_part, partition->start); |
744 |
|
else |
745 |
|
pupa_util_info ("BSD partition %d,%c starts from %lu", |
746 |
|
partition->dos_part, partition->bsd_part + 'a', |
747 |
|
partition->start); |
748 |
|
|
749 |
if (hdg.start == partition->start) |
if (hdg.start == partition->start) |
750 |
{ |
{ |
751 |
dos_part = partition->dos_part; |
dos_part = partition->dos_part; |
779 |
} |
} |
780 |
|
|
781 |
close (fd); |
close (fd); |
782 |
|
|
783 |
|
pupa_util_info ("%s starts from %lu", os_dev, hdg.start); |
784 |
|
|
785 |
if (hdg.start == 0) |
if (hdg.start == 0) |
786 |
return name; |
return name; |
787 |
|
|
788 |
|
pupa_util_info ("opening the device %s", name); |
789 |
disk = pupa_disk_open (name); |
disk = pupa_disk_open (name); |
790 |
free (name); |
free (name); |
791 |
|
|
792 |
if (! disk) |
if (! disk) |
793 |
return 0; |
return 0; |
794 |
|
|
795 |
pupa_partition_iterate (disk, find_partition); |
if (pupa_partition_iterate (disk, find_partition) != PUPA_ERR_NONE) |
796 |
|
{ |
797 |
|
pupa_disk_close (disk); |
798 |
|
return 0; |
799 |
|
} |
800 |
|
|
801 |
if (dos_part < 0) |
if (dos_part < 0) |
802 |
{ |
{ |
803 |
pupa_disk_close (disk); |
pupa_disk_close (disk); |