tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: Issues with lseek(2) on a block device
Hello, thanks to everyone who responded with their suggestions. Using
various non-portable ioctls I can device size on most platforms, for
both block and raw devices.
This is more convoluted than a single lseek() call, but it is what it
is. If anyone wants to do something similar, then the following example
can give you a good start.
/*
* devsize.c
* gcc -DNETBSD -Wall -Wextra -pedantic -o devsize devsize.c
*/
#include <assert.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#if defined(NETBSD)
#include <sys/dkio.h>
#endif
#if defined(FREEBSD)
#include <sys/disk.h>
#endif
#if defined(MACOS)
#include <sys/disk.h>
#endif
#if defined(LINUX)
#include <linux/fs.h>
#endif
/*
* Use lseek() to get device size in bytes.
* This should be portable, but on some platforms returns 0 bytes,
* in which case nonportable ioctl should be used.
*/
static void print_devsize_lseek(int fd)
{
off_t size;
size = lseek(fd, 0, SEEK_END);
assert(size >= 0);
printf("lseek SEEK_END = %ju bytes\n", (uintmax_t)size);
}
/* NetBSD, FreeBSD */
#if defined(DIOCGMEDIASIZE)
static void print_devsize_DIOCGMEDIASIZE(int fd)
{
int int_val;
off_t size;
/* This sets size to total number of bytes */
int_val = ioctl(fd, DIOCGMEDIASIZE, &size);
assert(int_val >= 0);
printf("ioctl DIOCGMEDIASIZE = %ju bytes\n", (uintmax_t)size);
}
#endif
/* MacOS */
#if defined(DKIOCGETBLOCKCOUNT) && defined(DKIOCGETBLOCKSIZE)
static void print_devsize_DKIOCGETBLOCKCOUNT(int fd)
{
int int_val
uint64_t block_count;
uint32_t block_size;
/* Total block count */
int_val = ioctl(fd, DKIOCGETBLOCKCOUNT, &block_count);
assert(int_val >= 0);
/* Block size */
int_val = ioctl(fd, DKIOCGETBLOCKSIZE, &block_size);
assert(int_val >= 0);
printf("ioctl DKIOCGETBLOCKCOUNT = %ju bytes\n",
(uintmax_t)block_count * (uintmax_t)block_size);
}
#endif
/* Linux */
#if defined(BLKGETSIZE)
static void print_devsize_BLKGETSIZE(int fd)
{
int int_val;
unsigned long size;
/* This sets size to number of 512-byte blocks */
int_val = ioctl(fd, BLKGETSIZE, &size);
assert(int_val >= 0);
printf("ioctl BLKGETSIZE = %ju bytes\n", (uintmax_t)size * 512);
}
#endif
/* Linux */
#if defined(BLKGETSIZE64)
static void print_devsize_BLKGETSIZE64(int fd)
{
int int_val;
uint64_t size;
/* This sets size to total number of bytes */
int_val = ioctl(fd, BLKGETSIZE64, &size);
assert(int_val >= 0);
printf("ioctl BLKGETSIZE = %ju bytes\n", (uintmax_t)size);
}
#endif
int main(int argc, char *argv[])
{
int fd;
if (argc != 2)
{
fprintf(stderr, "Usage: devsize <device>\n");
exit(EXIT_FAILURE);
}
/* Open device */
fd = open(argv[1], O_RDONLY);
assert(fd >= 0);
print_devsize_lseek(fd);
#if defined(DIOCGMEDIASIZE)
print_devsize_DIOCGMEDIASIZE(fd);
#endif
#if defined(DKIOCGETBLOCKCOUNT) && defined(DKIOCGETBLOCKSIZE)
print_devsize_DKIOCGETBLOCKCOUNT(fd);
#endif
#if defined(BLKGETSIZE)
print_devsize_BLKGETSIZE(fd);
#endif
#if defined(BLKGETSIZE64)
print_devsize_BLKGETSIZE64(fd);
#endif
}
Home |
Main Index |
Thread Index |
Old Index