~ubuntu-branches/ubuntu/precise/util-linux/precise-proposed

« back to all changes in this revision

Viewing changes to lib/blkdev.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Langasek
  • Date: 2011-06-20 22:31:50 UTC
  • mfrom: (1.6.3 upstream) (4.5.1 sid)
  • Revision ID: james.westby@ubuntu.com-20110620223150-lz8wrv0946ihcz3z
Tags: 2.19.1-2ubuntu1
* Merge from Debian unstable, remaining changes:
  - Build for multiarch.
  - Add pre-depends on multiarch-support.
  - configure.ac: don't try to be clever about extracting a path name from
    $libdir to append to /usr in a way that's not overridable; instead,
    reuse the built-in configurable libexecdir.
  - Fix up the .pc.in files to know about libexecdir, so our substitutions
    don't leave us with unusable pkg-config files.
  - Install custom blkid.conf to use /dev/.blkid.tab since we don't
    expect device names to survive a reboot
  - Mention mountall(8) in fstab(5) manpages, along with its special
    options.
  - Since upstart is required in Ubuntu, the hwclock.sh init script is not
    called on startup and the hwclockfirst.sh init script is removed.
  - Drop depends on initscripts for the above.
  - Replace hwclock udev rule with an Upstart job.
  - For the case where mount is called with a directory to mount, look
    that directory up in mountall's /lib/init/fstab if we couldn't find
    it mentioned anywhere else.  This means "mount /proc", "mount /sys",
    etc. work.
  - mount.8 points to the cifs-utils package, not the obsolete smbfs one. 
* Dropped changes:
  - mount.preinst: lsb_release has been fixed in lucid and above to be
    usable without configuration, so we don't have to diverge from Debian
    here anymore.
* Changes merged upstream:
  - sfdisk support for '+' with '-N'
  - mount/umount.c: fix a segfault on umount with empty mtab entry
  - Fix arbitrary unmount with fuse security issue

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
 
2
2
#include <sys/types.h>
 
3
#include <sys/stat.h>
3
4
#include <sys/ioctl.h>
4
5
#include <unistd.h>
 
6
#include <stdint.h>
 
7
 
 
8
#ifdef HAVE_LINUX_FD_H
 
9
#include <linux/fd.h>
 
10
#endif
 
11
 
 
12
#ifdef HAVE_SYS_DISKLABEL_H
 
13
#include <sys/disklabel.h>
 
14
#endif
 
15
 
 
16
#ifdef HAVE_SYS_DISK_H
 
17
#ifdef HAVE_SYS_QUEUE_H
 
18
#include <sys/queue.h> /* for LIST_HEAD */
 
19
#endif
 
20
#include <sys/disk.h>
 
21
#endif
5
22
 
6
23
#ifdef __FreeBSD_kernel__
7
24
#include <sys/disk.h>
23
40
 
24
41
off_t
25
42
blkdev_find_size (int fd) {
26
 
        off_t high, low;
27
 
 
28
 
        low = 0;
29
 
        for (high = 1; high > 0 && blkdev_valid_offset (fd, high); high *= 2)
 
43
        uintmax_t high, low = 0;
 
44
 
 
45
        for (high = 1024; blkdev_valid_offset (fd, high); ) {
 
46
                if (high == UINTMAX_MAX)
 
47
                        return -1;
 
48
 
30
49
                low = high;
 
50
 
 
51
                if (high >= UINTMAX_MAX/2)
 
52
                        high = UINTMAX_MAX;
 
53
                else
 
54
                        high *= 2;
 
55
        }
 
56
 
31
57
        while (low < high - 1)
32
58
        {
33
 
                const off_t mid = (low + high) / 2;
 
59
                uintmax_t mid = (low + high) / 2;
34
60
 
35
61
                if (blkdev_valid_offset (fd, mid))
36
62
                        low = mid;
45
71
int
46
72
blkdev_get_size(int fd, unsigned long long *bytes)
47
73
{
48
 
        /* TODO: use stat as well */
 
74
#ifdef DKIOCGETBLOCKCOUNT
 
75
        /* Apple Darwin */
 
76
        if (ioctl(fd, DKIOCGETBLOCKCOUNT, bytes) >= 0) {
 
77
                *bytes <<= 9;
 
78
                return 0;
 
79
        }
 
80
#endif
49
81
 
50
82
#ifdef BLKGETSIZE64
 
83
        {
51
84
#ifdef __linux__
52
 
        int ver = get_linux_version();
53
 
        /* kernels 2.4.15-2.4.17, had a broken BLKGETSIZE64 */
54
 
        if (ver >= KERNEL_VERSION (2,6,0) ||
55
 
           (ver >= KERNEL_VERSION (2,4,18) && ver < KERNEL_VERSION (2,5,0)))
 
85
                int ver = get_linux_version();
 
86
 
 
87
                /* kernels 2.4.15-2.4.17, had a broken BLKGETSIZE64 */
 
88
                if (ver >= KERNEL_VERSION (2,6,0) ||
 
89
                   (ver >= KERNEL_VERSION (2,4,18) && ver < KERNEL_VERSION (2,5,0)))
56
90
#endif
57
 
                if (ioctl(fd, BLKGETSIZE64, bytes) >= 0)
58
 
                        return 0;
 
91
                        if (ioctl(fd, BLKGETSIZE64, bytes) >= 0)
 
92
                                return 0;
 
93
        }
59
94
#endif /* BLKGETSIZE64 */
60
95
 
61
96
#ifdef BLKGETSIZE
68
103
                }
69
104
        }
70
105
 
71
 
        return -1;
72
106
#endif /* BLKGETSIZE */
73
107
 
74
 
#ifdef __FreeBSD_kernel__
75
 
        {
76
 
                off_t size;
77
 
 
78
 
                if (ioctl(fd, DIOCGMEDIASIZE, &size) >= 0) {
79
 
                        *bytes = size;
80
 
                        return 0;
81
 
                }
82
 
        }
 
108
#ifdef DIOCGMEDIASIZE
 
109
        /* FreeBSD */
 
110
        if (ioctl(fd, DIOCGMEDIASIZE, bytes) >= 0)
 
111
                return 0;
83
112
#endif
84
113
 
 
114
#ifdef FDGETPRM
 
115
        {
 
116
                struct floppy_struct this_floppy;
 
117
 
 
118
                if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) {
 
119
                        *bytes = this_floppy.size << 9;
 
120
                        return 0;
 
121
                }
 
122
        }
 
123
#endif /* FDGETPRM */
 
124
 
 
125
#ifdef HAVE_SYS_DISKLABEL_H
 
126
        {
 
127
                /*
 
128
                 * This code works for FreeBSD 4.11 i386, except for the full device
 
129
                 * (such as /dev/ad0). It doesn't work properly for newer FreeBSD
 
130
                 * though. FreeBSD >= 5.0 should be covered by the DIOCGMEDIASIZE
 
131
                 * above however.
 
132
                 *
 
133
                 * Note that FreeBSD >= 4.0 has disk devices as unbuffered (raw,
 
134
                 * character) devices, so we need to check for S_ISCHR, too.
 
135
                 */
 
136
                int part = -1;
 
137
                struct disklabel lab;
 
138
                struct partition *pp;
 
139
                char ch;
 
140
                struct stat st;
 
141
 
 
142
                if ((fstat(fd, &st) >= 0) &&
 
143
                    (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)))
 
144
                        part = st.st_rdev & 7;
 
145
 
 
146
                if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
 
147
                        pp = &lab.d_partitions[part];
 
148
                        if (pp->p_size) {
 
149
                                 *bytes = pp->p_size << 9;
 
150
                                 return 0;
 
151
                        }
 
152
                }
 
153
        }
 
154
#endif /* HAVE_SYS_DISKLABEL_H */
 
155
 
 
156
        {
 
157
                struct stat st;
 
158
 
 
159
                if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
 
160
                        *bytes = st.st_size;
 
161
                        return 0;
 
162
                }
 
163
                if (!S_ISBLK(st.st_mode))
 
164
                        return -1;
 
165
        }
 
166
 
85
167
        *bytes = blkdev_find_size(fd);
86
168
        return 0;
87
169
}