21
38
blkdev_find_size (int fd) {
25
for (high = 1; high > 0 && blkdev_valid_offset (fd, high); high *= 2)
39
uintmax_t high, low = 0;
41
for (high = 1024; blkdev_valid_offset (fd, high); ) {
42
if (high == UINTMAX_MAX)
47
if (high >= UINTMAX_MAX/2)
27
53
while (low < high - 1)
29
const off_t mid = (low + high) / 2;
55
uintmax_t mid = (low + high) / 2;
31
57
if (blkdev_valid_offset (fd, mid))
42
68
blkdev_get_size(int fd, unsigned long long *bytes)
44
/* TODO: use stat as well */
70
#ifdef DKIOCGETBLOCKCOUNT
72
if (ioctl(fd, DKIOCGETBLOCKCOUNT, bytes) >= 0) {
46
78
#ifdef BLKGETSIZE64
48
int ver = get_linux_version();
49
/* kernels 2.4.15-2.4.17, had a broken BLKGETSIZE64 */
50
if (ver >= KERNEL_VERSION (2,6,0) ||
51
(ver >= KERNEL_VERSION (2,4,18) && ver < KERNEL_VERSION (2,5,0)))
81
int ver = get_linux_version();
83
/* kernels 2.4.15-2.4.17, had a broken BLKGETSIZE64 */
84
if (ver >= KERNEL_VERSION (2,6,0) ||
85
(ver >= KERNEL_VERSION (2,4,18) && ver < KERNEL_VERSION (2,5,0)))
53
if (ioctl(fd, BLKGETSIZE64, bytes) >= 0)
87
if (ioctl(fd, BLKGETSIZE64, bytes) >= 0)
55
90
#endif /* BLKGETSIZE64 */
68
102
#endif /* BLKGETSIZE */
104
#ifdef DIOCGMEDIASIZE
106
if (ioctl(fd, DIOCGMEDIASIZE, bytes) >= 0)
112
struct floppy_struct this_floppy;
114
if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) {
115
*bytes = this_floppy.size << 9;
119
#endif /* FDGETPRM */
121
#ifdef HAVE_SYS_DISKLABEL_H
124
* This code works for FreeBSD 4.11 i386, except for the full device
125
* (such as /dev/ad0). It doesn't work properly for newer FreeBSD
126
* though. FreeBSD >= 5.0 should be covered by the DIOCGMEDIASIZE
129
* Note that FreeBSD >= 4.0 has disk devices as unbuffered (raw,
130
* character) devices, so we need to check for S_ISCHR, too.
133
struct disklabel lab;
134
struct partition *pp;
138
if ((fstat(fd, &st) >= 0) &&
139
(S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)))
140
part = st.st_rdev & 7;
142
if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
143
pp = &lab.d_partitions[part];
145
*bytes = pp->p_size << 9;
150
#endif /* HAVE_SYS_DISKLABEL_H */
155
if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
159
if (!S_ISBLK(st.st_mode))
70
163
*bytes = blkdev_find_size(fd);