~csurbhi/ubuntu/maverick/e2fsprogs/e2fsprogs.fix-505719

« back to all changes in this revision

Viewing changes to lib/blkid/getsize.c

  • Committer: Bazaar Package Importer
  • Author(s): Matt Zimmerman
  • Date: 2004-09-19 09:43:14 UTC
  • mto: (8.1.1 lenny) (1.2.3 upstream)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20040919094314-2tafd19i76fhu6ei
Tags: upstream-1.35
ImportĀ upstreamĀ versionĀ 1.35

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * getsize.c --- get the size of a partition.
 
3
 *
 
4
 * Copyright (C) 1995, 1995 Theodore Ts'o.
 
5
 *
 
6
 * %Begin-Header%
 
7
 * This file may be redistributed under the terms of the
 
8
 * GNU Lesser General Public License.
 
9
 * %End-Header%
 
10
 */
 
11
 
 
12
#define _LARGEFILE_SOURCE
 
13
#define _LARGEFILE64_SOURCE
 
14
 
 
15
#include <stdio.h>
 
16
#if HAVE_UNISTD_H
 
17
#include <unistd.h>
 
18
#endif
 
19
#if HAVE_ERRNO_H
 
20
#include <errno.h>
 
21
#endif
 
22
#include <fcntl.h>
 
23
#ifdef HAVE_LINUX_FD_H
 
24
#include <sys/ioctl.h>
 
25
#include <linux/fd.h>
 
26
#endif /* HAVE_LINUX_FD_H */
 
27
#ifdef HAVE_SYS_DISKLABEL_H
 
28
#include <sys/ioctl.h>
 
29
#include <sys/disklabel.h>
 
30
#include <sys/stat.h>
 
31
#endif /* HAVE_SYS_DISKLABEL_H */
 
32
 
 
33
#include "blkidP.h"
 
34
 
 
35
#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
 
36
#define BLKGETSIZE _IO(0x12,96) /* return device size */
 
37
#endif
 
38
 
 
39
#ifdef APPLE_DARWIN
 
40
#include <sys/ioctl.h>
 
41
#include <sys/disk.h>
 
42
 
 
43
#define BLKGETSIZE DKIOCGETBLOCKCOUNT32
 
44
#endif /* APPLE_DARWIN */
 
45
 
 
46
static int valid_offset(int fd, blkid_loff_t offset)
 
47
{
 
48
        char ch;
 
49
 
 
50
        if (blkid_llseek(fd, offset, 0) < 0)
 
51
                return 0;
 
52
        if (read(fd, &ch, 1) < 1)
 
53
                return 0;
 
54
        return 1;
 
55
}
 
56
 
 
57
/*
 
58
 * Returns the number of blocks in a partition
 
59
 */
 
60
blkid_loff_t blkid_get_dev_size(int fd)
 
61
{
 
62
#ifdef BLKGETSIZE
 
63
        unsigned long size;
 
64
#endif
 
65
        blkid_loff_t high, low;
 
66
#ifdef FDGETPRM
 
67
        struct floppy_struct this_floppy;
 
68
#endif
 
69
#ifdef HAVE_SYS_DISKLABEL_H
 
70
        int part = -1;
 
71
        struct disklabel lab;
 
72
        struct partition *pp;
 
73
        char ch;
 
74
        struct stat st;
 
75
#endif /* HAVE_SYS_DISKLABEL_H */
 
76
 
 
77
#ifdef BLKGETSIZE
 
78
        if (ioctl(fd, BLKGETSIZE, &size) >= 0)
 
79
                return (blkid_loff_t)size << 9;
 
80
#endif
 
81
#ifdef FDGETPRM
 
82
        if (ioctl(fd, FDGETPRM, &this_floppy) >= 0)
 
83
                return (blkid_loff_t)this_floppy.size << 9;
 
84
#endif
 
85
#ifdef HAVE_SYS_DISKLABEL_H
 
86
#if 0
 
87
        /*
 
88
         * This should work in theory but I haven't tested it.  Anyone
 
89
         * on a BSD system want to test this for me?  In the meantime,
 
90
         * binary search mechanism should work just fine.
 
91
         */
 
92
        if ((fstat(fd, &st) >= 0) && S_ISBLK(st.st_mode))
 
93
                part = st.st_rdev & 7;
 
94
        if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
 
95
                pp = &lab.d_partitions[part];
 
96
                if (pp->p_size)
 
97
                        return pp->p_size << 9;
 
98
        }
 
99
#endif
 
100
#endif /* HAVE_SYS_DISKLABEL_H */
 
101
 
 
102
        /*
 
103
         * OK, we couldn't figure it out by using a specialized ioctl,
 
104
         * which is generally the best way.  So do binary search to
 
105
         * find the size of the partition.
 
106
         */
 
107
        low = 0;
 
108
        for (high = 1024; valid_offset(fd, high); high *= 2)
 
109
                low = high;
 
110
        while (low < high - 1)
 
111
        {
 
112
                const blkid_loff_t mid = (low + high) / 2;
 
113
 
 
114
                if (valid_offset(fd, mid))
 
115
                        low = mid;
 
116
                else
 
117
                        high = mid;
 
118
        }
 
119
        return low + 1;
 
120
}
 
121
 
 
122
#ifdef TEST_PROGRAM
 
123
int main(int argc, char **argv)
 
124
{
 
125
        blkid_loff_t bytes;
 
126
        int     fd;
 
127
 
 
128
        if (argc < 2) {
 
129
                fprintf(stderr, "Usage: %s device\n"
 
130
                        "Determine the size of a device\n", argv[0]);
 
131
                return 1;
 
132
        }
 
133
 
 
134
        if ((fd = open(argv[1], O_RDONLY)) < 0)
 
135
                perror(argv[0]);
 
136
 
 
137
        bytes = blkid_get_dev_size(fd);
 
138
        printf("Device %s has %Ld 1k blocks.\n", argv[1], bytes >> 10);
 
139
 
 
140
        return 0;
 
141
}
 
142
#endif